使用流在Java中复制 - 丢失数据/字节

时间:2015-10-11 12:24:42

标签: java file io stream copy

我对使用流复制文件的方法有疑问:

void *

复制例如图像,.txt文件或有时视频文件时出现问题,错误“文件大小不匹配”。发生。当我比较源文件和目标文件大小时,大小确实不匹配,但打开后的图像似乎也是完整的,视频也是如此。可见的问题是文本文件 - 复制并丢失几个字节后,没有任何内容丢失,但在文件的末尾有几行标有“NUL”的某种标记 - 使用Notepad ++查看这些内容。

我尝试使用Files中的copy()方法,它正常工作,但我无法找出为什么我的方法丢失了字节。

非常感谢您的帮助,我无法在任何地方找到解决方案。

1 个答案:

答案 0 :(得分:0)

读取循环是问题:

while(is.read(buffer) > 0) {
    read += buffer.length;
    os.write(buffer);
    first = Math.round(read / src.length() * 100);
    if(first != second) {
        System.out.println(first + " % copied.");
    }
    second = Math.round(read / src.length() * 100);
}

is.read(buffer)返回读取的字节数。首先,您必须检查它是否大于或等于零,因为read的契约允许它在缓冲区大小为零时读取0个字节。但除此之外 - 你需要保持这个值,因为你必须只写你读的字节数。

通常,文件的大小不是4096的倍数。因此,最后一次读取将读取少于4096个字节。 read合同实际上说,如果当时可用的字节数减少,它甚至可以读取少于4096个。

因此,如果您没有准确写出已读取的内容,则您编写的缓冲区的一部分将包含上一次读取的值,如果文件小于4096字节,则为零。

所以纠正它:

int numRead;

while( (numRead = is.read(buffer)) >= 0) {
    read += numRead;
    os.write(buffer,0,numRead);
    first = Math.round(read / src.length() * 100);
    if(first != second) {
        System.out.println(first + " % copied.");
    }
    second = Math.round(read / src.length() * 100);
}

但实际上,建议每当您的副本涉及至少一个文件时使用Files类,并避免java.io.File支持Path,{{1}中的操作可用}和Paths