1

我在一些 Java 代码中使用内存映射文件来快速写入 2G 文件。我将整个文件映射到内存中。我的解决方案遇到的问题是,如果我正在写入的文件神秘地消失了,或者磁盘出现了某种类型的错误,那么这些错误不会冒泡到 Java 代码中。

事实上,从 Java 代码来看,我的编写似乎成功完成了。这是我为模拟此类故障而创建的单元测试:

File twoGigFile = new File("big.bin");
RandomAccessFile raf = new RandomAccessFile(twoGigFile, "rw");
raf.setLength(Integer.MAX_VALUE);
raf.seek(30000); // Totally arbitrary
raf.writeInt(42);
raf.writeInt(42);

MappedByteBuffer buf = raf.getChannel().map(MapMode.READ_WRITE, 0, Integer.MAX_VALUE);
buf.force();
buf.position(1000000); // Totally arbitrary
buf.putInt(0);

assertTrue(twoGigFile.delete());

buf.putInt(0);
raf.close();

此代码运行时完全没有任何错误。这对我来说是一个相当大的问题。我似乎找不到任何关于此类问题的内容。有谁知道如何让内存映射文件正确抛出异常?或者是否有另一种方法可以确保数据实际写入文件?

我试图避免使用 RandomAccessFile,因为它们比内存映射文件慢得多。但是,可能没有任何其他选择。

4

1 回答 1

2

你不能。引用 JavaDoc:

映射字节缓冲区的全部或部分可能随时变得不可访问 [...] 尝试访问映射字节缓冲区的不可访问区域不会更改缓冲区的内容,并且会导致在当时引发未指定的异常访问权限或稍后的某个时间。

原因如下:当您使用映射缓冲区时,您正在更改内存,而不是文件。在操作系统尝试将缓冲块写入磁盘之前,内存恰好由文件支持这一事实是无关紧要的,这完全由操作系统管理(即,您的应用程序不会知道它正在发生)。

如果您希望文件在您下方消失,那么您将不得不使用替代机制来查看是否会发生这种情况。一种可能性是偶尔使用 a 触摸文件RandomAccessFile,并捕获它将抛出的错误。根据您的操作系统,即使这样也可能还不够:例如,在 Linux 上,对于那些具有打开句柄的程序存在一个文件,即使该文件已从外部删除。

于 2012-09-26T21:26:59.667 回答