【发布时间】: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。 -
断点应该在
try的finally部分。