我何时需要在将文件写入磁盘时指定编码?

时间:2016-07-13 08:30:52

标签: java encoding utf-8

我有一个示例方法,它使用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个字节,因此是垃圾值。这是正确的还是我的理解完全错了?

2 个答案:

答案 0 :(得分:2)

您正在复制每个字节的文件字节,因此您无需关心字符编码。

根据经验:

使用各种InputStreamOutputStream实现进行逐字节处理(如文件复制)。 有一些方便的方法来直接处理文本,如PrintStream.println()。请注意,因为大多数都使用默认的平台特定编码。

使用各种ReaderWriter实施方案来阅读和撰写文字。

如果您需要在逐字节和文本处理之间进行转换,请使用InputStreamReaderOutputStreamWriter进行显式文件编码。

不要依赖默认编码。默认的字符编码是特定于平台的(例如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编码。

InputStreamOutputStreamReaderWriterRandomAccessFile构成了基本的IO功能,足以满足大多数用例的需求。对于高级IO(例如,内存映射文件,......),请查看包java.nio

答案 1 :(得分:1)

请阅读您的代码! (至少复制部分;-))

复制这两个文件时,请按byte复制byte。因此,无法转换为String

当您将String写入文件时,需要在bytebyte[])数组中进行转换(有时间接转换)。你需要指定你的编码。

当您读取文件以获取String时,您需要知道其编码才能正确执行。 Java不会“跳过”任何byte,但您需要再次进行转换:从byte[]String