写字节数组时出现IOException

时间:2012-08-30 11:02:33

标签: java file-io nio ioexception

我在尝试写一个大字节数组时得到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。 谁能解释我做错了什么? 感谢。

3 个答案:

答案 0 :(得分: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并且重复调用此方法,则映射可能会失败。例如你的虚拟内存耗尽。

答案 1 :(得分: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并直接在其中写入数据更为合适。如果需要,您仍然可以将其映射。

答案 2 :(得分:0)

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

java ... -Xmx 1024m ...