我在Windows XP中有一个大文件 - 它的38GB。 (虚拟机映像)
我似乎无法复制它。
在桌面上拖动 - 出现错误“系统资源不足以完成所请求的服务”
使用Java - FileChannel.transferTo(0,fileSize,dest)对所有文件都失败> 2GB
使用Java - 在100Mb块中的FileChannel.transferTo()在~18Gb之后失败
java.io.IOException: Insufficient system resources exist to complete the requested service
at sun.nio.ch.FileDispatcher.write0(Native Method)
at sun.nio.ch.FileDispatcher.write(FileDispatcher.java:44)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:72)
at sun.nio.ch.IOUtil.write(IOUtil.java:28)
at sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:198)
at sun.nio.ch.FileChannelImpl.transferToTrustedChannel(FileChannelImpl.java:439)
at sun.nio.ch.FileChannelImpl.transferTo(FileChannelImpl.java:510)
我的意思是 - 电脑有3GB的RAM。一个100GB的缓冲区应该足够了!?!?
显然DOS命令“copy”和“xcopy”也会失败。
(编辑)我试过COPY& XCOPY - 这些失败并出现同样的错误。 XCOPY似乎也花了很长时间。
我听说过Robocopy,但它没有复制单个文件?
我真的觉得Windows现在就输了。当然微软已经听说过大于几GB的文件?
谢谢!
答案 0 :(得分:2)
在Java中,不要尝试在单个操作中复制整个文件。 transferTo()
方法适用于文件的块;不是作为高级文件复制方法。在循环中调用transferTo()
,并假设count
个字节的数据将在RAM中(即,使该参数更低以适应RAM)。
FileChannel src = ...
FileChannel dst = ...
final long CHUNK = 16 * 1024 * 1024; /* 16 Mb */
for (long pos = 0; pos < fileSize; ) {
pos += src.transferTo(pos, CHUNK, dst);
}
transferTo()
JavaDoc中关于它“比简单循环更有效”的评论指的是频道间通信可以比频道到用户空间更优化的事实。渠道。它不意味着可以避免所有循环。
答案 1 :(得分:2)
我是Vmware ESX用户,我有30个生产VM,最大的是232GB。我将我的VM实例备份到内部SATA驱动器上,然后每周将其复制一次到外部eSata。我使用teracopy(免费),在3GB的XP机器上平均以45MB / s的速度运行。
希望有所帮助 Sailen
答案 2 :(得分:1)
嗯 - 我没有找到一种有效的方法。
Windows中的所有打包工具都不会复制该文件。拖放,COPY,XCOPY,java - 都无法复制文件。
我想复制文件的原因是在进行操作系统升级之前进行备份。
最后我启动了knoppix并复制了它。
答案 3 :(得分:0)
答案 4 :(得分:0)
也可能存在硬件问题。 我怀疑你没有太多时间,但是你可以试试dumber流解决方案并且不设置大缓冲区(8-16MB就足够了):
public static void copy(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[1024 * 1024 * 8]; // 8MB
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
}
public static void main(String args[]) {
if (args.length != 2) {
System.err.println("wrong argument count");
System.exit(1);
}
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(new File(args[0]));
out = new FileOutputStream(new File(args[1]));
copy(in, out);
} catch (Exception e) {
e.printStackTrace();
}
if (in != null) { try { in.close(); } catch (Exception e) {}}
if (out != null) { try { out.close(); } catch (Exception e) {}}
}
答案 5 :(得分:0)
你确定文件系统实际上能够处理这么大的文件(例如FAT32不能)吗?请查看此链接以获取详细信息http://www.ntfs.com/ntfs_vs_fat.htm
系统是32位还是64位?在32位上,您可能无法复制大于2-4Gb的文件。
另外,你说rsync为你准备好了。我有一个非常好的经验,在近原生速度下复制2个硬盘驱动器。我有很多小文件..你似乎在大blob上。
您也可以尝试将大blob拆分为更小的blob:)
答案 6 :(得分:0)
final long CHUNK = 16 * 1024 * 1024; /* 16 Mb */
for (long pos = 0; pos < fileSize; pos++) {
pos += src.transferTo(pos, CHUNK, dst);
}
这确实有效!只需确保你的src和dst是FileChannel对象(分别是输入,输出)
答案 7 :(得分:0)
另一个可能的答案是Files.copy(java NIO 2),例如:
Path sourcePath = Paths.get("big-file.dat");
Path destinationPath = Paths.get("big-file-copy.dat");
try {
Files.copy(sourcePath, destinationPath,
StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
// something else went wrong
e.printStackTrace();
}