5

我正在开发一个 sc2replay 解析工具。我在 MPQLIB http://code.google.com/p/mpqlib/之上构建它

不幸的是,该工具使用文件通道来读取 bzip 文件,并使用map(MapMode.READ_ONLY, hashtablePosition, hashTableSize);

调用该函数后,关闭文件通道不会在进程中释放文件。具体来说,我无法重命名/移动文件。

该问题出现在 Java 7 中,并且在 Java 6 上运行良好。

这是一个简单的代码片段来复制它:

    FileInputStream f = new FileInputStream("test.SC2Replay");
    FileChannel fc = f.getChannel();

    fc.map(MapMode.READ_ONLY, 0,1);

    fc.close();

    new File("test.SC2Replay").renameTo(new File("test1.SC2Replay"));

注释掉 fc.map 将允许您重命名文件。

PS from here我应该关闭 FileChannel 吗?

它指出您不需要同时关闭文件通道和文件流,因为关闭一个会关闭另一个。我也尝试关闭一个或两个,但仍然没有奏效。

在 Java 7 上使用 FileChannel.map 读取数据后重命名文件是否有解决方法,因为现在每个人似乎都有 Java 7?

4

3 回答 3

2

再会,

似乎 FileChannel.map 会导致 java 7 出现问题。如果使用 FileChannel.map,则无法再关闭该文件。

一个快速的解决方法是使用 FileChannel.map(MapMode.READ_ONLY, position, length)

您可以使用

ByteBuffer b = ByteBuffer.allocate(length); 
fc.read(b,position);
b.rewind();
于 2012-10-25T11:19:18.487 回答
0

这是一个记录在案的错误。该错误报告涉及 Java 1.4,他们认为这是一个文档错误。关闭文件通道不会关闭底层流。

于 2012-10-25T09:38:36.980 回答
0

如果您使用 Sun JRE,您可以通过强制转换到他们的实现并告诉它自己释放来作弊。如果您不依赖正在关闭的文件或从不打算使用另一个 JRE,我只建议您这样做。

在某个时候,我希望这样的东西能成为适当的公共 API。

try (FileInputStream stream = new FileInputStream("test.SC2Replay");
     FileChannel channel = stream.getChannel()) {

    MappedByteBuffer mappedBuffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, 1);
    try {
        // do stuff with it
    } finally {
        if (mappedBuffer instanceof DirectBuffer) {
            ((DirectBuffer) mappedBuffer).cleaner().clean();
        }
    }
}
于 2015-08-18T01:47:20.257 回答