在我的一个项目中,当使用Java将文件写入MS Windows中的本地文件系统时,我遇到了一个非常意外的行为。 文件名由应用程序生成,包含无效的char':'。该程序没有防范(现在是),但我期望在将内容写入该文件时出现IOException。然而,情况要复杂得多。
以下是我所遇到的SSCE:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class FileWriter {
public static void main(String[] args) throws IOException {
File home = new File(System.getProperty("user.dir"));
final String fileName = "invalidf:ile.txt";
// Some cleanup if you rerun the example
File otherFile = new File(home, "invalidf");
if (otherFile.exists()) {
assertTrue(otherFile.delete());
}
File file = new File(home, fileName);
if (file.exists()) {
assertTrue(file.delete());
}
// The real scenario. Writing some content to an illegal file name
FileOutputStream out = new FileOutputStream(file);
final String content = "some test content";
out.write(content.getBytes());
out.close();
// Since the write operation does not throw an exception, it is expected some file has been written
assertTrue(file.isFile());
assertTrue(file.canRead());
// This should usually throw an exception since the file was deleted in the cleanup section.
assertTrue(otherFile.exists());
// Now we try to read the data and make sure it really got stored.
FileInputStream in = new FileInputStream(file);
assert in.available() > 0;
byte[] fileContent = new byte[in.available()];
assertTrue(in.read(fileContent) == content.getBytes().length);
assertTrue(Arrays.equals(fileContent, content.getBytes()));
}
private static void assertTrue(boolean flag) {
if (!flag) {
throw new RuntimeException("Assertion failed!");
}
}
}
那么问题是什么呢:
Windows会按预期列出新文件invalidf
而不是invalidf:ile.txt
。文件大小显示为0字节,读取该文件(使用编辑器和Java代码)不返回任何内容。最初编写的文件似乎不存在。
使用Java读取文件invalidf:ile.txt
会显示最初编写的内容(如上面的代码所示)。
那么这里的问题是什么?好像有两个文件可用。一个可见但看似空的文件和一个带有真实内容的“隐藏”文件。但是,如果我删除空文件,则无法再访问“隐藏”文件。因此文件系统似乎将两个文件视为相同。
这可能与我使用的Windows和Java版本有关(使用Java 6和Windows 7进行测试)。
答案 0 :(得分:3)
搜索“Windows备用数据流”。解释here。
备用数据流是附加到文件的数据流,但与主文件内容无关。似乎“:”是在Windows中指定ADS的方式。从上面的链接中,您可以将备用流的内容读取为:
notepad invalidf:ile.txt