【问题标题】:Reading a file using utf-8 that is encoded in utf-8 doesn't work, but reading the same file using "windows-1252" or "iso-8859-1" does使用 utf-8 编码的 utf-8 读取文件不起作用,但使用“windows-1252”或“iso-8859-1”读取相同的文件可以
【发布时间】:2021-01-25 14:47:30
【问题描述】:

这里发生了什么?为什么当我使用 utf-8 读取文件时,它会在控制台中输出问号?

这是一个最小的工作示例:

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
    
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.apache.commons.io.FileUtils.writeStringToFile;
    
public class Main {
    
    public static void main(String... args) throws IOException {
    
        System.out.println("---------");
        System.out.println(Charset.defaultCharset());
        System.out.println("æ ø å");
        System.out.println("æ ø å");
        System.out.println("æ ø å");
    
        File inputFile  = new File(System.getProperty("user.dir") + "/input.md");
        File outputFile = new File(System.getProperty("user.dir") + "/output.md");
    
        String content, encoding;
    
        System.out.println("--------- windows-1252");
        encoding = "windows-1252";
        content = readFileToString(inputFile, encoding);
        System.out.println(content);
    
    
        System.out.println("--------- iso-8859-1");
        encoding = "iso-8859-1";
        content = readFileToString(inputFile, encoding);
        System.out.println(content);
    
    
        System.out.println("--------- utf-8");
        encoding = "utf-8";
        content = readFileToString(inputFile, encoding);
        System.out.println(content);
    
    
        writeStringToFile(outputFile, content, encoding);
    
    }
    
}

其中input.md 包含:(以 UTF-8 编码)

This is input.md. 'æ' 'ø' 'å'

运行上述代码产生

---------
windows-1252
æ ø å
æ ø å
æ ø å
--------- windows-1252
This is file C. 'æ' 'ø' 'å'.
--------- iso-8859-1
This is file C. 'æ' 'ø' 'å'.
--------- utf-8
This is file C. '�' '�' '�'.

当我使用 UTF-8 读取文件时,为什么会得到 ?这特别奇怪,因为文件是用 UTF-8 编码的

更新:我的控制台设置为“UTF-8”:

这是从输入文件中提取的字符串中每个字符的十六进制值的屏幕截图:

这是一个更好的十六进制隔离截图:

【问题讨论】:

  • 代码的图像是没有用的。我们不能复制和粘贴它,我们不能运行它或测试它,我们不能搜索它,视障用户不能用它做任何事情,就我自己来说,当它被缩放时我几乎看不到它以适应页面。请编辑您的问题并在该图像中添加文本——最好是一个包含您的代码的代码格式文本块,另一个包含您的输出。
  • @VGR 我编辑了这个问题,希望现在更清楚:)
  • systemProp.file.encoding=utf-8添加到项目根目录下的gradle.properties文件有帮助吗?在设置中切换到 IntelliJ IDEA 是否有帮助(macOS 上的首选项)|构建、执行、部署 |构建工具 |摇篮 | 使用构建和运行?
  • 还尝试为设置设置 UTF-8(macOS 上的首选项)|编辑 |文件编码 | 项目编码.
  • @Andrey 在设置下的“文件编码”选项卡中,一切都已被设置为 UTF-8。 screenshot。不,它没有帮助。

标签: java intellij-idea encoding utf-8 character-encoding


【解决方案1】:

代码对我来说看起来不错,您的 output.md 文件看起来也不错。所以这很可能只是控制台输出的问题。

您正在试验的 Unicode 字符在 Windows-1252 和 ISO-8859-1(æ = 0xE6ø = 0xF8å = 0xE5)中被编码为相同的单个字节,但在 UTF 中被编码为多个字节-8 (æ = 0xC3 0xA6, ø = 0xC3 0xB8, å = 0xC3 0xA5)。

以 Windows-1252 或 ISO-8859-1 格式读取 UTF-8 编码文件将分别解码每个字节,生成一个 string,其中每个字节包含一个单独的 char,而那些 chars 将具有与字节相同的数值。因此,您应该以包含字符0x00C3 0x00A60x00C3 0x00B80x00C3 0x00A5string 结尾。将这些 chars 输出到控制台作为 Windows-1252应该显示为 æ ø Ã¥,而不是 æ ø å

另一方面,以 UTF-8 格式读取 UTF-8 编码文件将正确解码文件,生成 stringchars 0x00E60x00F80x00E5。将 string 写入 UTF-8 编码文件应该会产生正确的字节序列(0xC3 0xA60xC3 0xB80xC3 0xA5),但输出与 Windows-1252 相同的 string 可能会导致数据丢失,但您应该按预期看到æ ø å,因为 Windows-1252 确实支持这些 Unicode 字符。

因此,您的结果实际上与我的预期相反。尽管Charset.defaultCharset() 报告了 Windows-1252,但我怀疑您的控制台实际上使用了不同的字符集作为其输出。

我建议您打印出content 字符串中单个chars 的数值,以查看input.md 是如何被每种编码实际解码的。您应该获得我上面提到的char 值。

【讨论】:

  • 编辑:我解决了这个问题,你说得对,这是与控制台输出相关的问题。
【解决方案2】:

对于有类似问题的人来说,问题在于控制台的编码(正如@Remy Lebeau 所指出的那样)。

我通过关注answer解决了这个问题

实际上,我在评论中关注了@Nicolas 对提到的答案的回答:

这也可以通过帮助 > 编辑自定义 VM 选项...然后重新启动 IntelliJ 进行访问。我确实尝试了所有方法:在 IntelliJ 中随处更改编码设置,更改属性文件、build.gradle 文件、IntelliJ、运行配置、环境变量等设置的 JVM 选项。还尝试更改系统范围的编码,除了这个

现在我得到了预期的输出:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-14
    • 2015-06-20
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    • 2016-05-10
    • 2012-07-26
    相关资源
    最近更新 更多