使用 FileChannel.transferTo() 方法复制文件,大小受限

______S_cs 2014-12-12 12:03:18
问题是这样的,想用 FileChannel.transFrom() / transTo() 方法来复制文件,但是发现在复制大文件的时候(2GB以上),transTo() 方法复制出来的文件只有 2GB,而 transFrom() 方法复制出来的文件大小一致,另外,如果用这两个方法复制稀疏文件,会导致稀疏文件占用磁盘空间变大、变得和文件大小差不多一样大,感觉就像复制完的文件已经不是稀疏文件了一样。
那么,问题来了:
1,为什么 tranTo() 方法复制出来的文件,大小只有2GB?
2,为什么 tranFrom() / transTo() 复制稀疏文件的时候会导致复制出来的文件占用的磁盘空间变大?
另:盘符系统是NTFS
下面是代码,再下面是复制出来的文件(截图)


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;

public class test1 {
public static void main(String[] args) throws IOException {
FileChannel in1 = new FileInputStream("D:\\610OMG_81.iso").getChannel();
FileChannel out1 = new FileOutputStream("D:\\610OMG_81_transFrom.iso").getChannel();
try {
out1.transferFrom(in1, 0, in1.size());
} finally {
out1.close();
in1.close();
}

FileChannel in2 = new FileInputStream("D:\\610OMG_81.iso").getChannel();
FileChannel out2 = new FileOutputStream("D:\\610OMG_81_transTo.iso").getChannel();
try {
in2.transferTo(0, in2.size(), out2);
} finally {
out2.close();
in2.close();
}
}
}

...全文
4188 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
NDSC流氓 2018-11-25
  • 打赏
  • 举报
回复
引用 6 楼 NDSC流氓 的回复:
给后面的人看
可以跟到transferTo里面的源码
查看FileChannelImpl里面transferTo的实现源码
public long transferTo(long var1, long var3, WritableByteChannel var5) throws IOException {
this.ensureOpen();
if (!var5.isOpen()) {
throw new ClosedChannelException();
} else if (!this.readable) {
throw new NonReadableChannelException();
} else if (var5 instanceof FileChannelImpl && !((FileChannelImpl)var5).writable) {
throw new NonWritableChannelException();
} else if (var1 >= 0L && var3 >= 0L) {
long var6 = this.size();
if (var1 > var6) {
return 0L;
} else {
int var8 = (int)Math.min(var3, 2147483647L);
if (var6 - var1 < (long)var8) {
var8 = (int)(var6 - var1);
}

long var9;
if ((var9 = this.transferToDirectly(var1, var8, var5)) >= 0L) {
return var9;
} else {
return (var9 = this.transferToTrustedChannel(var1, (long)var8, var5)) >= 0L ? var9 : this.transferToArbitraryChannel(var1, var8, var5);
}
}
} else {
throw new IllegalArgumentException();
}
}

关键在
else if (var1 >= 0L && var3 >= 0L) {
long var6 = this.size();
if (var1 > var6) {
return 0L;
} else {
int var8 = (int)Math.min(var3, 2147483647L);
if (var6 - var1 < (long)var8) {
var8 = (int)(var6 - var1);
}

long var9;
if ((var9 = this.transferToDirectly(var1, var8, var5)) >= 0L) {
return var9;
} else {
return (var9 = this.transferToTrustedChannel(var1, (long)var8, var5)) >= 0L ? var9 : this.transferToArbitraryChannel(var1, var8, var5);
}
}

这段,会把长度设置为2147483647L也就是大概2GB的大小
所以需要对FileChannel.size()返回值进行判断,当它返回值大于0时始终要执行transferTo方法
因为transferTo单次只能处理2gb左右的长度,同时计算position偏移量

写错了.是对transferTo方法的返回值进行判断
NDSC流氓 2018-11-25
  • 打赏
  • 举报
回复
给后面的人看
可以跟到transferTo里面的源码
查看FileChannelImpl里面transferTo的实现源码
public long transferTo(long var1, long var3, WritableByteChannel var5) throws IOException {
this.ensureOpen();
if (!var5.isOpen()) {
throw new ClosedChannelException();
} else if (!this.readable) {
throw new NonReadableChannelException();
} else if (var5 instanceof FileChannelImpl && !((FileChannelImpl)var5).writable) {
throw new NonWritableChannelException();
} else if (var1 >= 0L && var3 >= 0L) {
long var6 = this.size();
if (var1 > var6) {
return 0L;
} else {
int var8 = (int)Math.min(var3, 2147483647L);
if (var6 - var1 < (long)var8) {
var8 = (int)(var6 - var1);
}

long var9;
if ((var9 = this.transferToDirectly(var1, var8, var5)) >= 0L) {
return var9;
} else {
return (var9 = this.transferToTrustedChannel(var1, (long)var8, var5)) >= 0L ? var9 : this.transferToArbitraryChannel(var1, var8, var5);
}
}
} else {
throw new IllegalArgumentException();
}
}

关键在
else if (var1 >= 0L && var3 >= 0L) {
long var6 = this.size();
if (var1 > var6) {
return 0L;
} else {
int var8 = (int)Math.min(var3, 2147483647L);
if (var6 - var1 < (long)var8) {
var8 = (int)(var6 - var1);
}

long var9;
if ((var9 = this.transferToDirectly(var1, var8, var5)) >= 0L) {
return var9;
} else {
return (var9 = this.transferToTrustedChannel(var1, (long)var8, var5)) >= 0L ? var9 : this.transferToArbitraryChannel(var1, var8, var5);
}
}

这段,会把长度设置为2147483647L也就是大概2GB的大小
所以需要对FileChannel.size()返回值进行判断,当它返回值大于0时始终要执行transferTo方法
因为transferTo单次只能处理2gb左右的长度,同时计算position偏移量
lukezhang-123 2018-10-14
  • 打赏
  • 举报
回复
while (position < size) { long count = inChannel.transferTo(position, size, outChannel); if (count > 0) { position += count; size-= count; } } 可能没有一次transferTo完成,看看返回的count 值大小
liyuhao6878 2016-11-24
  • 打赏
  • 举报
回复
我想知道FileChannel.transFrom() / transTo()怎么输出文件传输进度?
______S_cs 2014-12-12
  • 打赏
  • 举报
回复
引用 1 楼 healer_kx 的回复:
http://www.cnblogs.com/interdrp/p/3785164.html
这个帖子还是没有关于为什么我的代码transTo()方法只能复制小于2GB文件的原因
______S_cs 2014-12-12
  • 打赏
  • 举报
回复
引用 1 楼 healer_kx 的回复:
http://www.cnblogs.com/interdrp/p/3785164.html
正在看帖,感谢回复
healer_kx 2014-12-12
  • 打赏
  • 举报
回复
http://www.cnblogs.com/interdrp/p/3785164.html

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧