【问题标题】:Cannot read special letters from UTF-8 txt file in java无法从 java 中的 UTF-8 txt 文件中读取特殊字母
【发布时间】:2013-05-20 20:53:47
【问题描述】:

我在 java 中遇到了 UTF-8 编码的问题。 我有一个 UTF-8 编码的 .txt 文件。我在记事本++中检查了该文件实际上是 UTF-8 编码的。 我尝试读取文件,但特殊字母显示不正确。

我使用以下代码和平:

        try {

        Scanner sc = new Scanner(new FileInputStream("file.txt"), "UTF-8");

        String str;

        while(sc.hasNextLine()) {
            str = sc.nextLine();
            roadNames.add(str);
            System.out.println(str);
        }

        sc.close();

    } catch(IOException e1) {
        System.out.println("The file was not found....");
    }

它在 Eclipse 中正确显示特殊字母,我将默认编码定义为 UTF-8,但在我生成的 jar 文件中没有。

真正对我有用的唯一方法是使用以下参数“java -Dfile.encoding=utf-8 -jar executable.jar”制作一个 .bat 文件,但我认为这不是一个好的解决方案。

此外,这也有效:

PrintStream out = new PrintStream(System.out, true, "UTF-8"); 
out.println(str);

更新

当我说

特殊字母显示不正确

我的意思是 System.out.println 打印一个字符串,其中特殊字母被替换为 ├à 而不是 å 例如。

事实证明

PrintStream out = new PrintStream(System.out, true, "UTF-8"); 
out.println(str);

毕竟不起作用 - 对此感到抱歉。

真正的问题不是我想让控制台打印出文本文档中的内容,而是文本文档中的每一行都包含一个名称,并且这个名称被添加到一个 ArrayList 中。然后我有一个 JTextField,当我开始在其中输入时,它会尝试通过在 ArrayList 中搜索最佳匹配名称来自动完成我输入的内容。如果不是因为编码问题,这非常有效,因为 JTextField 中的特殊字母没有正确显示。只有当我使用 Dfile.encoding=utf-8 参数时它才能正确显示

【问题讨论】:

  • “它正确显示特殊字母”是什么意思?您在 ecipe 中看到您的非拉丁符号,但是当您在 Windows 中打开 .bat 文件时,您会看到 ... ?如果您没有看到正确的字符,可能是因为您没有在 Windows 上安装正确的语言包。这不是 Java 问题。如果文件中的字节正确则与Java无关
  • 想在哪里展示它们? > 但特殊字母显示不正确。
  • 如果您在谈论这一行:System.out.println(str); 那么问题是,您的控制台无法显示这些字符。除此之外,你做的一切都是正确的。
  • 突击队提示没有正确显示像æ,ø,å 这样的字符,但是带有一些奇怪的符号,字符,é 也没有正确显示,而且还带有一些奇怪的符号。这仅在 Eclipse 中有效,甚至在我使用 Dfile.encoding=utf-8 参数运行 jar 文件时也无效。我有一个 JTextfield,其中包含来自插入 roadNames ArrayList 的字符串之一的字符串。当我使用 Dfile.encoding=utf-8 参数时,JTextField 会正确显示 æ、ø、å,但否则不会
  • 您是否正在从文件中读取roadNames 列表?如果是这样,当您在cmd.exe 控制台中运行命令type file.txt 时会看到什么?听起来你的 Windows 设置是罪魁祸首;你可以获得更多背景here.

标签: java encoding utf-8


【解决方案1】:

Java 将使用平台默认编码,除非您指定其他内容。

听起来您的平台默认值(Windows 设置)不是 UTF-8,因此在您未指定 file.encoding 属性或向 PrintStream 构造函数提供编码的情况下,默认编码用来。在这种情况下,当发现无法编码的字符时,将使用该编码器的替换字符。这通常是 '�' 或 '?'。

操作系统指示它可能无法显示您希望打印的某些字符。您可以忽略该提示,并希望获得最好的结果,或者您可以用保证显示的内容替换麻烦的字符。默认是替换;如果您想使用风险更大的方法,则必须明确。


更新:根据原始问题更新中提供的信息,听起来问题在于读取文件,而不是其输出。

使用平台默认编码是一种例外情况。您应该遵循的一般模式是在每次将字节序列解码为字符串时明确指定编码。编码是您正在阅读的流所固有的,并且通常独立于您的代码恰好在其上运行的系统。当您从控制台或类似设备读取时,例外情况。否则,应该有一些元数据或约定来指定编码,例如 HTTP 标头、文件中嵌入的属性或需要特定编码的某些标准。

以下是从 UTF-8 编码文件中读取道路名称的方法:

Set<String> roadNames = new TreeSet<>();
try (InputStream bytes = new FileInputStream("file.txt")) {
  /* See how I'm specifying the UTF-8 encoding explicitly? */
  Reader chars = new InputStreamReader(bytes, StandardCharsets.UTF_8);
  BufferedReader lines = new BufferedReader(chars);
  while (true) {
    String line = lines.readLine();
    if (line == null)
      break;
    roadNames.add(line);
  }
}

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。使用 Charset.forName("cp866") 应该会有所帮助。

    BufferedReader brI = new BufferedReader(new InputStreamReader(cmd.getInputStream(), Charset.forName("cp866")));
            String result;
            while ((result = brI.readLine()) != null){
                System.out.println(result);
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-28
      • 1970-01-01
      • 2021-06-10
      • 2017-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多