FileChannel.transferTo用于Windows中的大文件

使用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))字节对于这种方法是最佳的。

Windows对最大传输大小有硬性限制,如果超过它,则会出现运行时exception。 所以你需要调整。 你给出的第二个版本是优越的,因为它不假设文件是​​通过一个transferTo()调用完全transferTo() ,这与Javadoc一致。

无论如何,设置大于1MB的传输大小是毫无意义的。

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

 while (position < size) { long count = inChannel.transferTo(position, size, outChannel); if (count > 0) { position += count; size-= count; } } 

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

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

Quote:在win2000中,transferTo()不传输文件> 2 ^ 31-1个字节。 它抛出了一个exception“java.io.IOException:存在不足的系统资源来完成所请求的服务。” 解决方法是每次循环复制64Mb,直到没有更多数据。

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