【问题标题】:Why Windows console code page influences the compilation and running of a Java program with ANSI characters?为什么 Windows 控制台代码页会影响带有 ANSI 字符的 Java 程序的编译和运行?
【发布时间】:2021-07-04 03:36:54
【问题描述】:

根据From compilation to runtime, how does Java String encoding really work,Java 类文件中的字符串与使用的代码页无关。但是我在GBK(中国使用的ANSI编码)机器上的Java程序中发现了以下问题。 假设以下字符:

字符串

ANSIStringAsUTF 是 AString 用 ANSI 编码并用 UTF-8 解码时的样子。

UTFStringAsANSI 是 AString 使用 UTF-8 编码并使用 ANSI 解码时的样子。

所以当我用 ANSI 在 notepad++ 中输入 AString 时,保存文件并用 ANSI 打开文件,它看起来是正确的。如果我用 UTF-8 打开文件,它会显示 ANSIStringAsUTF。 当我使用 UTF-8 在记事本 ++ 中输入 AString 时,保存文件并使用 UTF-8 打开文件,它看起来是正确的。如果我用 ANSI 打开文件,它会显示 UTFStringAsANSI。很好!

public class Main {
    public static void main(String[] args) {
        System.out.println(*AString*);
    }
}

我在 Windows 控制台中使用 ANSI 代码页 936 编译上述以 UTF-8 编码的 java 文件,然后运行它。它看起来和预期的一样。 我使用 chcp 命令将代码页更改为 65001(UTF-8) 并运行它,它显示 ANSIStringAsUTF。

我在带有 UTF-8 代码页的 Windows 控制台中编译上面以 UTF-8 编码的 java 文件,然后运行它。它看起来和预期的一样。 我使用 chcp 命令将代码页更改为 936 并运行它,它显示 UTFStringAsANSI。

行为与使用 notepad++ 编辑文件相同,即使用的代码页决定 Java 中字符串的编码和解码。谁能告诉我为什么?抱歉这个冗长的问题。

【问题讨论】:

  • “使用的代码页决定了 Java 中字符串的编码和解码”——我认为你没有证明这一点。您已经证明它会影响字符串在控制台上的显示方式。我建议您将“内存中存在的字符串”和“调用 System.out.println 的结果”这两个想法分开。理想情况下,更改您的代码以转储 UTF-16 代码单元(作为整数)以及作为文本的字符串。这样您就可以轻松区分。
  • Java 字符串独立于编码。但源代码不是。而控制台不是。而读写文本文件则不然。对于所有这些,需要理解和控制所涉及的编码。许多人遇到编码问题并添加 print 语句,从而引入更多编码问题而不是解决问题。您想提高对编码的理解,还是有特定的问题需要解决?
  • 感谢 cmets。我确实了解字符串编码和源代码等之间的区别。但是 1. 程序以某种方式正确打印的事实表明 AString 在两种情况下都在编译期间正确解码。 2. 程序以某种方式打印不正确的事实表明 Java 没有根据使用的代码页正确编码输出字符串。 3. 两种情况不同,说明使用的代码页对编译的类有影响。 4. 更糟糕的是,结果各不相同,有时我在使用 UTF-8 打开时在两个编译类中都发现了 UTFStringAsANSI。

标签: java encoding utf-8 decoding ansi


【解决方案1】:

javac 命令有一个指定编码的选项:

-encoding encoding
指定源文件使用的字符编码,例如 EUC-JP 和 UTF-8。 如果未指定-encoding 选项,则使用平台默认转换器。

由于您没有指定选项,因此命令提示符的代码页用于确定平台默认编码。

通常的良好做法是始终以 UTF-8 保存 Java 源文件,并在手动编译时显式指定 -encoding UTF-8,因此编译不受环境设置的影响。

更常见的做法是不手动编译,而是使用 Maven、Gradle 或 Ant 等构建工具,并在构建脚本中指定结束选项。这样您就不必再考虑它了。

强烈建议使用 IDE,而不是像 Notepad++ 这样的文本编辑器,并将 IDE 配置为始终使用 UTF-8。

【讨论】:

  • 谢谢。我了解该选项并遵循惯例。我遇到问题并尝试通过手动执行所有操作来查找原因。源代码以 UTF-8 编码并使用 & 不带 -encoding UTF-8 选项进行编译,结果不会改变。
猜你喜欢
  • 2017-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-20
  • 1970-01-01
  • 1970-01-01
  • 2020-03-12
相关资源
最近更新 更多