【问题标题】:FileOutputStream try-with-resources doesn't close file descriptorFileOutputStream try-with-resources 不关闭文件描述符
【发布时间】:2019-09-06 17:10:19
【问题描述】:

我的代码可以将一些特定的大型(大约 15k 个条目)二进制序列化文件存档提取到磁盘上的文件夹中。

public void extractExact(Path absolutePath, DoubleConsumer progressConsumer) throws IOException
{
    ...
    // Extract to file channel
    try (final FileOutputStream fos = new FileOutputStream(absolutePath.toFile()))
    {
        PakExtractor.Extract(pakFile, Entry, fos.getChannel(), progressConsumer);
    }
 }

extractExact 函数调用存档中的每个条目。

在此之后,如果我尝试调用 Files.delete(<archive_file_path>) 方法 - 我会得到一个异常:

java.nio.file.FileSystemException:该进程无法访问该文件,因为它正被另一个进程使用。

我在 Process Explorer 搜索中检查了我的存档文件,它说我的 java.exe 打开了大约 15k 文件(与存档中的文件一样多)

这只发生在 Windows (jdk1.8.0_162) 中。在 Linux 上,“僵尸”打开的文件没有任何问题。

【问题讨论】:

  • 可能是 Windows 中的一些服务,它正在索引/分析文件?一些桌面搜索索引、防病毒等?
  • 也许您需要在下次通话前致电fos.flush()?可能还有东西要写。
  • 您的 try-with-resources 使用是正确的。我多次观察到 Windows 在文件被程序关闭后保持锁定几秒钟,甚至是非 Java 程序(但我无法找到有关它的现有 Stack Exchange 问题)。
  • 但是为什么要绕道呢?只需使用try(FileChannel ch = FileChannel.open(absolutePath, StandardOpenOption.WRITE, StandardOpenOption.CREATE)) { … },不需要.toFile(),不需要.getChannel()。如果你想在之后删除文件,你可以在open 调用中指定StandardOpenOption.DELETE_ON_CLOSE
  • 断点应该在tryfinally部分。

标签: java windows java-8 io


【解决方案1】:

终于 - 我们找到了解决方案。非常感谢@Netherwire。 FileChannel 类有 map 方法,该方法对文件描述符进行一些隐式复制操作,因此使用时要小心。 Here 是更多信息。

【讨论】:

  • 我遇到了将my previous comment 中提到的DELETE_ON_CLOSE 选项与map 一起使用的场景。这样做的好处是,当在close() 时间仍然存在阻止删除的映射时,在清理映射或在 JVM 退出时间作为最后手段时,文件将被删除。
猜你喜欢
  • 2017-05-06
  • 2019-03-12
  • 2017-12-04
  • 2014-05-05
  • 2020-01-01
  • 1970-01-01
  • 2016-09-29
  • 2011-10-16
  • 1970-01-01
相关资源
最近更新 更多