1

IOException: Map Failed在尝试编写大字节数组时得到了。我使用下面的方法将字节数组写入文件

private static void write(byte[] data) throws Exception {
        File file = new File("C:/temp/file.json");
        int length = data.length;
        RandomAccessFile raf = new RandomAccessFile(file, "rw");
        FileChannel fc = raf.getChannel();
        MappedByteBuffer buffer = fc.map(FileChannel.MapMode.READ_WRITE, 0, length);
        for (int i = 0; i < length; i++) {
            buffer.put(data[i]);
        }
}

字节数组约为 270mb。谁能解释我做错了什么?谢谢。

4

3 回答 3

4

我不知道为什么地图失败了,但我不会像你那样做。

FileOutputStream out = new FileOutputStream(filename);
out.write(data);
out.close();

要逐步做到这一点,您可以使用

FileOutputStream out = new FileOutputStream(filename);
for(int i = 0; i < data.length; i += 8192)
    out.write(data, i, Math.min(data.length-i, 8192));
out.close();

如果您有 32 位 JVM 并且重复调用此方法,则映射可能会失败。例如,您用完了虚拟内存。

于 2012-08-30T11:07:52.967 回答
1

我认为该解决方案与具有该mmap()功能的 C 中的解决方案相同。如果您刚刚创建了文件,您应该在其中寻找data.length-1偏移并在该位置写入一个字节,以便在映射之前拥有该大小的文件。当我不在 C 中执行此操作时,我在访问映射内存时会出现内存损坏。

类似的东西应该可以工作:

private static void write(byte[] data) throws Exception {
        File file = new File("C:/temp/file.json");
        int length = data.length;
        RandomAccessFile raf = new RandomAccessFile(file, "rw");

        FileChannel fc = raf.getChannel();
        fc.position(size-1);
        ByteBuffer bf = ByteBuffer.wrap(new byte[]{0x00});

        bf.flip();  // Not sure if flip is needed !!!!!!!

        fc.write(bf);

        MappedByteBuffer buffer = fc.map(FileChannel.MapMode.READ_WRITE, 0, length);
        for (int i = 0; i < length; i++) {
            buffer.put(data[i]);
        }
}

简单来说:你不能映射超过文件大小,这就是为什么你需要在映射之前增加文件大小。

这可以解释你的问题,但我认为打开一个FileOutputStream并直接在其中写入你的数据更合适。如果需要,您仍然可以在之后映射它。

于 2012-08-30T11:10:19.570 回答
0

您的 JVM 最大堆大小是否至少为 270*2 MB?您可以在用于启动 Java 的命令行上进行设置:

java ... -Xmx 1024m ...

于 2012-08-30T11:09:32.410 回答