我有一个示例方法,它使用InputStream和OutputStream将一个文件复制到另一个文件。在这种情况下,源文件以< UTF-8'编码。即使我在写入磁盘时没有指定编码,目标文件也具有正确的编码。但是,如果我必须将java.lang.String写入文件,我需要指定编码。那是为什么?
public static void copyFile() {
String sourceFilePath = "C://my_encoded.txt";
InputStream inStream = null;
OutputStream outStream = null;
try{
String targetFilePath = "C://my_target.txt";
File sourcefile =new File(sourceFilePath);
outStream = new FileOutputStream(targetFilePath);
inStream = new FileInputStream(sourcefile);
byte[] buffer = new byte[1024];
int length;
//copy the file content in bytes
while ((length = inStream.read(buffer)) > 0){
outStream.write(buffer, 0, length);
}
inStream.close();
outStream.close();
System.out.println("File "+targetFilePath+" is copied successful!");
}catch(IOException e){
e.printStackTrace();
}
}
我的猜测是,由于源文件具有正确的编码,并且由于我们一次读写一个字节,因此工作正常。并且java.lang.String是' UTF-16'默认情况下,如果我们将其写入文件,它一次读取一个字节而不是2个字节,因此是垃圾值。这是正确的还是我的理解完全错了?
答案 0 :(得分:2)
您正在复制每个字节的文件字节,因此您无需关心字符编码。
根据经验:
使用各种InputStream
和OutputStream
实现进行逐字节处理(如文件复制)。
有一些方便的方法来直接处理文本,如PrintStream.println()
。请注意,因为大多数都使用默认的平台特定编码。
使用各种Reader
和Writer
实施方案来阅读和撰写文字。
如果您需要在逐字节和文本处理之间进行转换,请使用InputStreamReader
和OutputStreamWriter
进行显式文件编码。
不要依赖默认编码。默认的字符编码是特定于平台的(例如Windows-ANSI aka Cp1252 for Windows,通常是Linux上的UTF-8)。
示例:如果您需要读取UTF-8文本文件:
BufferedReader reader =
new BufferedReader(new InputStreamReader(new FileInputStream(inFile), "UTF-8"));
避免使用FileReader
,因为FileReader
始终使用默认编码。
特殊情况:如果您需要随机访问文件,则应使用RandomAccessFile
。有了它,您可以在任意位置读取和写入数据块。您可以读取和写入原始字节块,也可以使用便捷方法来读取和写入文本。但是你应该仔细阅读文档。例如。方法readUTF()
和writeUTF()
使用修改后的UTF-8编码。
InputStream
,OutputStream
,Reader
,Writer
和RandomAccessFile
构成了基本的IO功能,足以满足大多数用例的需求。对于高级IO(例如,内存映射文件,......),请查看包java.nio
。
答案 1 :(得分:1)
请阅读您的代码! (至少复制部分;-))
复制这两个文件时,请按byte
复制byte
。因此,无法转换为String
。
当您将String
写入文件时,需要在byte
(byte[]
)数组中进行转换(有时间接转换)。你需要指定你的编码。
当您读取文件以获取String
时,您需要知道其编码才能正确执行。 Java不会“跳过”任何byte
,但您需要再次进行转换:从byte[]
到String
。