在Windows上编写具有无效名称的文件时出现意外行为

时间:2013-11-22 10:41:06

标签: java io filesystems

在我的一个项目中,当使用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进行测试)。

1 个答案:

答案 0 :(得分:3)

搜索“Windows备用数据流”。解释here

备用数据流是附加到文件的数据流,但与主文件内容无关。似乎“:”是在Windows中指定ADS的方式。从上面的链接中,您可以将备用流的内容读取为:

notepad invalidf:ile.txt