文件无法使用Java正确复制

时间:2014-06-16 01:05:38

标签: java

我编写了一个只读取文件内容并将其写入新副本的小程序。这与文本文件完美配合,但对于PNG和视频文件,它无法正确创建文件(图像全黑或视频无法播放)。我知道有些API可以用一行复制文件,但我很想知道为什么这不起作用。这是代码:

import java.io.*;

public class CopyFile
{
    public static void main(String[] args) throws Exception
    {
        File file = new File("test.mp4");
    File copy = new File("copy.mp4");

    InputStreamReader input = new InputStreamReader(new FileInputStream(file));
    OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(copy));

    System.out.println(input.ready());

    while(input.ready())
    {
        int i = input.read();
        //System.out.print( (char) ( (byte) i));
        out.write(i);
    }

    input.close();
    out.flush();
    out.close();
}

}

2 个答案:

答案 0 :(得分:4)

ReaderWriter用于读取字符流(即文本)。图片和视频是二进制数据,而不是文本,如果您通过字符流传递它们可能会损坏。这是因为,根据字符集,字节和字符之间不一定存在可逆映射。如果解释为字符,则某些字节序列是乱码,然后将乱码写回文件。

使用您直接打开的InputStreamOutputStream,而不是将其整理为ReaderWriter,它将正常运行。这些是字节流,可以处理任何类型的数据。

如,

InputStream input = new FileInputStream(file);
OutputStream out = new FileOutputStream(copy);

P.S。这仍然会很慢。您可以将流包装在BufferedInputStreamBufferedOutputStream中以获得提高性能的简单方法,尽管单行复制API可能仍然会更快。

答案 1 :(得分:4)

  1. 除非您知道输入是文字,否则请勿使用ReaderWriter。使用InputStreamOutputStream.
  2. 不要使用ready(),或者,对于Sotirios的好处,available()。它们都不是流结束的有效测试。它们都关心输入是否可以在没有阻塞的情况下读取这根本不是一回事。见Javadoc。
  3. 您没有正确检测到流的结尾。如果read()返回-1,您仍然将其复制到输出。
  4. 一次复制单个字符或单个字节非常慢。
  5. 在Java中复制流的规范方法如下:

    while ((count = in.read(buffer)) > 0)
    {
        out.write(buffer, 0, count);
    }
    

    其中countint,buffer是任何大小为零的byte[],通常为8192.