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();
}
}
超级啃爹,到了2147483647L就不传输了
var 8 就是 transferToDirectly 方法的单次处理长度,会对传入的var3(也就是由外部传入的 count 参数,即transferTo的第二个参数)
进行Math.min判断,而2147483647L 其实是字节,也就是2GB – 1个字节的长度,这就是transferTo单次处理长度的极限长度
所以如果处理超过2GB的文件就要循环执行transferTo方法,直至处理长度和文件长度一样为止
public class CopyFile {
public static void main(String[] args) {
File source = new File("I:\\fileSize4GB.txt");
File target = new File("G:\\test.txt");
try (FileInputStream is = new FileInputStream(source); FileChannel in = is.getChannel();
FileOutputStream os = new FileOutputStream(target); FileChannel out = os.getChannel()) {
int position = 0;
long size = in.size();
while (0 < size) {
long count = in.transferTo(position, size, out);
if (count > 0) {
position += count;
size -= count;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
这样就搞定啦