尝试复制大文件时NIO出错

时间:2011-01-12 08:24:27

标签: java nio

我有将文件复制到其他位置的代码。

public static void copyFile(String sourceDest, String newDest) throws IOException {

    File sourceFile = new File(sourceDest);
    File destFile = new File(newDest);
    if (!destFile.exists()) {
        destFile.createNewFile();
    }

    FileChannel source = null;
    FileChannel destination = null;
    try {
        source = new FileInputStream(sourceFile).getChannel();
        destination = new FileOutputStream(destFile).getChannel();
        destination.transferFrom(source, 0, source.size());
    } finally {
        if (source != null) {
            source.close();
        }
        if (destination != null) {
            destination.close();
        }
    }

}
}

虽然复制小块,比如300-400 Mb,但一切都像魔术一样。但是,当我尝试复制1.5 Gb大小的文件时,它失败了。堆栈是:

  

运行:   12.01.2011 11:16:36 FileCopier主要   严重:复制文件时发生异常。再试一次。   java.io.IOException:映射失败           在sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:748)           at sun.nio.ch.FileChannelImpl.transferFromFileChannel(FileChannelImpl.java:527)           at sun.nio.ch.FileChannelImpl.transferFrom(FileChannelImpl.java:590)           在FileCopier.copyFile(FileCopier.java:64)           在FileCopier.main(FileCopier.java:27)   引起:java.lang.OutOfMemoryError:映射失败           at sun.nio.ch.FileChannelImpl.map0(Native Method)           at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:745)           ......还有4个   建立成功(总时间:0秒)

我还没与NIO密切合作。你能帮帮我吗?非常感谢你。

2 个答案:

答案 0 :(得分:5)

我想你可能已经被前一段时间遇到的old bug击中了。我没有尝试复制文件,而是寻找通过内存映射的文件,该文件也失败了。对我来说,解决方法是循环搜索文件并请求GCfinalizers不时运行。

内存映射的ByteBuffers在终结器中释放它们的映射,并为新的映射腾出空间。这非常难看,但至少它有效。让我们希望他们在即将到来的NIO迭代中做到这一点。

答案 1 :(得分:2)

您是内存映射文件,但32位JVM(我认为您正在使用)中的内存地址空间有限,因此map方法失败。我认为你不能映射超过1.3-1.4 GB的磁盘数据。你使用的是什么堆大小?

您可以尝试减小堆大小或使用64位JRE。或者,不要使用NIO将文件映射到内存来读取文件。相反,使用缓冲读写器的传统方式从一个文件读取数据到另一个文件。