关于FileChannel的transferTo方法复制超过2GB文件不完整的情况

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();
        }
    }
}

这样就搞定啦

关于Zeno Chen

本人涉及的领域较多,杂而不精 程序设计语言: Perl, Java, PHP, Python; 数据库系统: MySQL,Oracle; 偶尔做做电路板的开发,主攻STM32单片机
此条目发表在Java分类目录。将固定链接加入收藏夹。