【问题标题】:Writing to Buffered Writer UTF-8 Characters With Accents Are Coming Out Garbled写入带重音的缓冲 Writer UTF-8 字符出现乱码
【发布时间】:2019-12-11 21:22:11
【问题描述】:

我正在读取带有重音字符的 UTF-8 输入文件,读取这些行并将它们写回另一个文件(也是 UTF-8),但重音字符在输出中出现乱码。例如以下单词:

莱昂

马诺亚

输出为:

Le�n

马诺阿

我已经查看了这个问题的大约 100 个答案,这些答案都建议按照下面的代码所示读取和写入文件,但我一直得到相同的结果。

我已将代码分解为以下基本功能:

public class UTF8EncoderTest 
{
    public static void main(String[] args)
    {
        try 
        {
            BufferedReader inputFileReader = new BufferedReader(new InputStreamReader(new FileInputStream("utf8TestInput.txt"), "UTF-8"));
            BufferedWriter outputFileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("utf8TestOutput.txt"), "UTF-8"));

            String line = inputFileReader.readLine();
            while (line != null) 
            {
                outputFileWriter.write(line + "\r\n");          
                line = inputFileReader.readLine();
            }
            inputFileReader.close();
            outputFileWriter.close();

            System.out.println("Finished!");
        }
        catch (IOException e) 
        {
            e.printStackTrace();
        }       
    }
}

但这仍然会导致输出文件中出现乱码。任何帮助将不胜感激!

【问题讨论】:

  • search Stackoverflow for this:我可以保证答案已经在这里了。
  • 如问题中所述,我已经在 StackOverflow 上搜索了这个问题的答案,他们都给出了相同的答案,即上面编码的内容。 BufferedReader inputFileReader = new BufferedReader(new InputStreamReader(new FileInputStream("utf8TestInput.txt"), "UTF-8"));和 BufferedWriter outputFileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("utf8TestOutput.txt"), "UTF-8"));
  • 您能否提供您正在测试的输入和输出文件的原始十六进制转储?
  • 那么可以合理地假设您正在阅读的内容实际上根本不是 UTF-8。输入文件中的前几个字节是什么?
  • León 在 UTF-8 中是字节 4C 65 C3 B3 6E。 UTF-8 中的Le�n 是字节4C 65 EF BF BD 6EEF BF BD 是 Unicode 代码点 U+FFFD REPLACEMENT CHARACTER 的 UTF-8 编码形式。无论输入字符串León 编码的字节是什么,它都不是UTF-8,导致您的InputStreamReader 误解ó(代码点U+00F3)并将其替换为line 变量中的代码点U+FFFD ,然后您的OutputStreamWriter(正确地)以字节EF BF BD 用UTF-8 写出。所以仔细检查输入文件的编码,它不是你想象的那样。

标签: java utf-8 fileoutputstream bufferedwriter


【解决方案1】:

我用你的例子试过你的代码,它没有问题(字符没有改变或丢失)。

在 Java 中处理字符集时的一些提示:

  1. Java 中的默认字符编码是 JVM 使用的字符编码。
  2. 默认情况下,JVM 使用平台编码,即服务器 (OS) 的字符编码。
  3. Java 在 JVM 启动时通过调用 System.getProperty("file.encoding","UTF-8") 来获取字符编码。因此,如果 Java 没有获得任何 file.encoding 属性,它会使用 UTF-8 字符编码。 最重要的一点要记住的是,Java 在其大多数核心类中缓存字符编码或系统属性file.encoding 的值,如InputStreamReader,在JVM 启动后需要字符编码。因此,如果您在应用程序运行时以编程方式更改系统属性file.encoding,您将不会在您的应用程序中看到所需的效果(更改),这就是为什么您应该始终使用提供给您的应用程序的自己的字符编码,如果需要将其设置为在启动 JVM 时设置字符编码或字符集。

如何获取默认字符编码?

  1. 获取默认字符编码的最简单方法是调用System.getProperty("file.encoding"),如果JVM 以-Dfile.encoding 属性启动或程序没有调用System.setProperty("file.encoding", someEncoding),它将返回默认字符编码。
  2. java.nio.Charset 提供了一个方便的静态方法Charset.defaultCharset(),它返回默认的字符编码。
  3. 通过使用InputStreamReader#getEncoding()

如何设置默认字符编码?

  1. 通过在 JVM 启动时提供 file.encoding 系统属性,例如: java -Dfile.encoding="UTF-8" HelloWorld
  2. 如果您无法控制 JVM 的启动方式,您可以将环境变量 JAVA_TOOL_OPTIONS 设置为 -Dfile.encoding="UTF-16" 或任何其他字符编码,当 JVM 在您的 windows 机器上启动时,它将被拾取。 JVM 还会在控制台上打印Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF16,以表明它已经选择了JAVA_TOOS_OPTIONS

或者,您可以尝试:

Path inputFilePath = Paths.get("utf8TestInput.txt");
BufferedReader inputFileReader = Files.newBufferedReader(inputFilePath, StandardCharsets.UTF_8);
Path outputFilePath = Paths.get("utf8TestOutput");
BufferedWriter outputFileWriter = Files.newBufferedWriter(outputFilePath, StandardCharsets.UTF_8);

【讨论】:

    猜你喜欢
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-22
    • 2011-10-03
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    相关资源
    最近更新 更多