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

标签 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.(ex: BufferedInput/OutputStream)

最佳答案

有两个问题(至少):

  1. 您使用 nextLine() 它将读取到下一个 "\r\n"', '\n''\r''\u2028''\u2029''\u0085' 和丢弃它发现的行分隔符(一个或两个字符)。由于您甚至没有使用 append(text).append('\n') 我怀疑这是否会正确复制多行文本,更不用说二进制文件了,其中每个可能的行终止符都可能意义不同。

  2. 您使用 ScannerStringBuilder,它们对二进制数据不安全。作为 new Scanner(java.io.InputStream) 上的文档状态:

    Bytes from the stream are converted into characters using the underlying platform's default charset.

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

如果您想复制任意(可能是二进制)文件,我建议您不要冒险并坚持使用 byte[] API。但是,在创建 ScannerPrintStream 时,您也可以使用已知接受所有字节序列不变的字符集,如 ISO-8859-1;您仍然需要避免使用抑制找到的行分隔符的行 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();
        }
    }

关于java - 如何使用IO Scanner/System.out复制视频和照片?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25347834/

相关文章:

java在用户输入之前在控制台中写字母

java - 在 2 个表中使用具有相同列名的 ResultSetMetaData

java - 使用 Scribe 获取带有特定主题标签的推文

html - 将视频放在网页上

iphone - 在iPhone 4上录制视频时可以播放音频吗?

java - 如何设置字符串的颜色

java - 将 int 转换为十六进制字符串,而不使用 Integer.toHexString();

java - 无法填充以 TreeSet 作为参数的 HashMap

android - Videogular Player 在 Android 智能手机上显示幻灯片

java - 在 Tomcat 上配置 simplelogger (slf4j)