使用DataInputStream逐字节复制文件在完成之前停止

时间:2014-09-28 07:38:34

标签: java io inputstream

我在java中编写了以下程序,使用DataInput \ Output Stream复制文件。

import java.io.*;
public class FileCopier {

    public static void main(String args[]) throws Exception
    {
        File file = new File("/home/Sample.mkv");
        File copy = new File("/home/Copy_of_Sample.mkv");
        if(copy.exists())
        {
            copy.delete();
        }
        copy.createNewFile();
        DataInputStream din = new DataInputStream(new FileInputStream(file));
        DataOutputStream dout = new DataOutputStream(new FileOutputStream(copy));
        byte c;
        c = 1;
        long time = System.currentTimeMillis();
        while(c!=-1)
        {
            c =  (byte) din.read();
            dout.write(c);
        }

        time = System.currentTimeMillis() - time;
        System.out.println(time);
    }
}

然而,我没有得到预期的结果。我知道read()方法DataInputStream从输入流中读取下一个字节并将其转换为int。在这里我再次将其转换为字节并将该字节写入另一个文件,但仍然没有按预期工作。我尝试复制的原始文件大小为8.5 MB,而复制的文件大小仅为5.3 MB。

Plz帮助我理解为什么会这样。

提前致谢, Nishant

3 个答案:

答案 0 :(得分:1)

DataInputStream的read()方法将数据的下一个字节作为0-255的值读取。 Java中的字节数据类型是有符号的,因此它的值从-128到127.这就是为什么当转换为一个字节时,某些值出现为-1会停止它。

您最好的选择是使用int。

int c = 0;
while(c!=-1)
{
    c =  din.read();
    dout.write(c);
}

使用int意味着将读取和写入正确的值。

(我没有足够的rep来评论,但是char是无符号的,Java中有两个字节。它的值永远不会是-1。)

答案 1 :(得分:1)

read方法返回一个整数,而不是一个字节。

  

从输入流中读取下一个数据字节。值字节是   返回为0到255范围内的int。如果没有可用的字节   因为已到达流的末尾,值为-1   返回。

因此,您将获得一个int,检查该值是否为-1,并将其转换回byte以将其写入输出流。

int c = -1; 
while((c =  din.read()) !=-1)
{
  dout.write((byte)c);
}
  

我知道read()方法DataInputStream从输入流中读取下一个字节并将其转换为int。

是。所以它应该是int c;而不是byte c;

  

这里我再次将其转换为字节并将该字节写入另一个文件

所以,这是你的错误。将byte再次转换为byte

  

我要复制的原始文件大小为8.5 MB,而复制的文件大小仅为5.3 MB。

正如所指出的那样,读取/遇到byte,其值'-1' End of file marker -1。 它通过'255'方法以值read()的整数形式返回。 您的代码在'-1' byte中将其存储为'c',导致while(c!=-1)检查失败并在中途终止。

答案 2 :(得分:0)

问题是之前的(byte)强制转换检查结果为-1,这是out-of-band用来表示EOF的InputStream.read哨兵值。

读取了大约5.3MB的为255的字节,以及(byte)255 == -1,这导致循环在输入结束之前终止。

将其改为,以便"字节"是演员。

int c;
while (true)
{
    c = din.read();
    if (c == -1) break;  // don't write EOF, ever
    dout.write(c);       // no cast at all, as it is write(int)
}

此外,这必须是效率最低的复制实现之一。使用缓冲流和read(byte[])是两种简单的方法,可以使更多更快。