简体   繁体   中英

How to use IO Scanner/System.out copying video and photos?

I use io scanner / System.out to copy text files. I tried using the same technique to copy pdf, video and image files. The result was that the files were copied, but they were corrupt (cannot open them). Also, the file size does not equal the original file size.

code

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: Not use IO other.(ex: BufferedInput/OutputStream)

There are two problems (at least):

  1. you use nextLine() which will read up to the next "\\r\\n"' , '\\n' , '\\r' , '\
' , '\
' or '\…' and discard what ever it found as line separator (one or two characters). As you are not even using append(text).append('\\n') I doubt that this will correctly copy multi-line text, let alone binary files where each of the possible line-terminators may have a different meaning.

  2. you use Scanner and StringBuilder which are not safe for binary data. As the Documentation on new Scanner(java.io.InputStream) states:

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

    If any byte-sequence in you input file is not valid as eg UTF-8 (which is a common default charset) it is silently replaced by a generic 'could not read input'-character. For text-files this can mean, that a 'ä' is converted to ' ', for binary files this can render the whole file unusable.

If you want to copy arbitrary (possibly binary) files I would recommend not taking any chances and stick to byte[] APIs. You could however also use a charset which is known to accept all byte-sequences unchanged like ISO-8859-1 when creating Scanner and PrintStream ; you would than still need to refrain from using line-APIs that suppress the found line-separator.

This should do the trick:

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();
        }
    }
}

pre Java 7 you need to use 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();
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM