10

使用 Java NIO 可以更快地复制文件。我主要通过互联网找到了两种方法来完成这项工作。

public static void copyFile(File sourceFile, File destinationFile) throws IOException {
    if (!destinationFile.exists()) {
        destinationFile.createNewFile();
    }

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

20 个对 Java 开发人员非常有用的 Java 代码片段中,我发现了一个不同的评论和技巧:

public static void fileCopy(File in, File out) throws IOException {
    FileChannel inChannel = new FileInputStream(in).getChannel();
    FileChannel outChannel = new FileOutputStream(out).getChannel();
    try {
        // inChannel.transferTo(0, inChannel.size(), outChannel); // original -- apparently has trouble copying large files on Windows
        // magic number for Windows, (64Mb - 32Kb)
        int maxCount = (64 * 1024 * 1024) - (32 * 1024);
        long size = inChannel.size();
        long position = 0;
        while (position < size) {
            position += inChannel.transferTo(position, maxCount, outChannel);
        }
    } finally {
        if (inChannel != null) {
            inChannel.close();
        }
        if (outChannel != null) {
            outChannel.close();
        }
    }
}

但我没有找到或理解什么是意思

“Windows 的幻数,(64Mb - 32Kb)”

它说inChannel.transferTo(0, inChannel.size(), outChannel)在 Windows 中有问题,32768 (= (64 * 1024 * 1024) - (32 * 1024)) 字节最适合这种方法。

4

3 回答 3

12

Windows 对最大传输大小有硬性限制,如果超过它,就会出现运行时异常。所以你需要调。您提供的第二个版本更好,因为它不假定文件已通过一次transferTo()调用完全传输,这与 Javadoc 一致。

无论如何,将传输大小设置为超过 1MB 是毫无意义的。

编辑您的第二个版本有缺陷。您应该减少size每次转移的金额。它应该更像:

while (size > 0) { // we still have bytes to transfer
    long count = inChannel.transferTo(position, size, outChannel);
    if (count > 0)
    {
        position += count; // seeking position to last byte transferred
        size-= count; // {count} bytes have been transferred, remaining {size}
    }
}
于 2011-09-13T08:05:31.580 回答
0

我读过它是为了与 Windows 2000 操作系统兼容。

来源:http ://www.rgagnon.com/javadetails/java-0064.html

Quote: 在win2000 中,transferTo() 不会传输大于2^31-1 字节的文件。它抛出异常“java.io.IOException:系统资源不足,无法完成请求的服务被抛出。” 解决方法是每次循环复制 64Mb,直到没有更多数据为止。

于 2014-01-04T03:26:41.080 回答
-1

似乎有轶事证据表明,在某些 Windows 版本上尝试一次传输超过 64MB 会导致复制速度慢。因此检查:这似乎是transferTo在 Windows 上实现操作的底层本机代码的一些细节的结果。

于 2011-09-11T16:12:21.323 回答