我使用 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)
最佳答案
有两个问题(至少):
您使用
nextLine()
它将读取到下一个"\r\n"'
,'\n'
、'\r'
、'\u2028'
、'\u2029'
或'\u0085'
和丢弃它发现的行分隔符(一个或两个字符)。由于您甚至没有使用append(text).append('\n')
我怀疑这是否会正确复制多行文本,更不用说二进制文件了,其中每个可能的行终止符都可能意义不同。您使用
Scanner
和StringBuilder
,它们对二进制数据不安全。作为new Scanner(java.io.InputStream)
上的文档状态:Bytes from the stream are converted into characters using the underlying platform's default charset.
如果您输入文件中的任何字节序列无效,例如UTF-8(这是一个常见的默认字符集)它被一个通用的“无法读取输入”字符默默地取代。对于文本文件,这可能意味着“ä”被转换为“�”,对于二进制文件,这可能导致整个文件无法使用。
如果您想复制任意(可能是二进制)文件,我建议您不要冒险并坚持使用 byte[]
API。但是,在创建 Scanner
和 PrintStream
时,您也可以使用已知接受所有字节序列不变的字符集,如 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/