如何使用IO Scanner / System.out复制视频和照片?

时间:2014-08-17 09:12:28

标签: java video system.out

我使用io scanner / System.out来复制文本文件。我尝试使用相同的技术来复制pdf,视频和图像文件。结果是文件被复制,但它们已损坏(无法打开它们)。此外,文件大小不等于原始文件大小。

import java.awt.Desktop;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Scanner;

public class ScannerTest {
    public static void main(String[] args) throws IOException {
         PrintStream out =System.out;
         long start = System.currentTimeMillis(); 
         copyFile(new File("H:\\a.pdf"), new File("H:\\b.pdf"));// 2 file input, output
         System.setOut(out);
         System.out.println(System.currentTimeMillis()-start);



}
static String text=null;
public static void copyFile(File input,File output) throws IOException{

    //Scanner read file
    Scanner in= new Scanner(new FileInputStream(input));
    StringBuilder builder  =new StringBuilder();
    try {
        while(in.hasNextLine()){

            text=in.nextLine();
            builder.append(text);

        }
    } catch (Exception e) {
        e.printStackTrace();
    }finally{
        in.close();
    }


    //System.out
    try {
        OutputStream outputStream = new FileOutputStream(output);
        PrintStream printStream = new PrintStream(outputStream);

        System.setOut(printStream);
        System.out.println(new String(builder));

        Desktop.getDesktop().open(output);
    } catch (Exception e) {

        e.printStackTrace();
    }


}

}

p / s:不使用IO other。(例如:BufferedInput / OutputStream)

1 个答案:

答案 0 :(得分:0)

有两个问题(至少):

  1. 您使用的nextLine()会阅读下一个"\r\n"''\n''\r''\u2028''\u2029''\u0085'并丢弃它所发现的行分隔符(一个或两个字符)。因为你甚至没有使用append(text).append('\n')我怀疑这会正确地复制多行文本,更不用说二进制文件,其中每个可能的行终止符可能有不同的含义。

  2. 您使用的ScannerStringBuilder对二进制数据不安全。正如new Scanner(java.io.InputStream)所述的文档:

      

    使用底层平台的默认字符集将流中的字节转换为字符。

    如果输入文件中的任何字节序列无效,例如UTF-8(这是一个常见的默认字符集)它默默地被一个通用的“无法读取输入”字符所取代。对于文本文件,这可能意味着'ä'被转换为' ',对于二进制文件,这可能导致整个文件无法使用。

  3. 如果你想复制任意(可能是二进制)文件,我建议不要冒任何机会并坚持使用byte[] API。但是,在创建ScannerPrintStream时,您也可以使用已知接受所有字节序列的字符集,如ISO-8859-1;你仍然需要避免使用压缩找到的行分隔符的line-API。

    这应该可以解决问题:

    import java.awt.Desktop;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.PrintStream;
    
    /**
     * Created for http://stackoverflow.com/a/25351502/1266906
     */
    public class CopyFile {
        public static void main(String[] args) {
            long start = System.currentTimeMillis();
            copyFile(new File("H:\\a.pdf"), new File("H:\\b.pdf"));// 2 file input, output
            System.out.println(System.currentTimeMillis() - start);
        }
    
        public static void copyFile(File input, File output) {
            try {
                try (FileInputStream inputStream = new FileInputStream(input);
                     OutputStream outputStream = new FileOutputStream(output)) {
                    byte[] buffer = new byte[4096];
                    do {
                        int readBytes = inputStream.read(buffer);
                        if (readBytes < 1) {
                            // end of file
                            break;
                        } else {
                            outputStream.write(buffer, 0, readBytes);
                        }
                    } while (true);
                }
    
                // Open result
                Desktop.getDesktop().open(output);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    在Java 7之前,您需要使用try-finally:

        public static void copyFile(File input, File output) {
            try {
                FileInputStream inputStream = new FileInputStream(input);
                try {
                    OutputStream outputStream = new FileOutputStream(output);
                    try {
                        byte[] buffer = new byte[4096];
                        do {
                            int readBytes = inputStream.read(buffer);
                            if (readBytes < 1) {
                                // end of file
                                break;
                            } else {
                                outputStream.write(buffer, 0, readBytes);
                            }
                        } while (true);
                    } finally {
                        outputStream.close();
                    }
                } finally {
                    inputStream.close();
                }
    
                // Open result
                Desktop.getDesktop().open(output);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }