【问题标题】:Characters "æ", "ø" "æ" in Java Strings (Windows)Java字符串中的字符“æ”,“ø”“æ”(Windows)
【发布时间】:2013-11-13 15:16:32
【问题描述】:

由于某种原因,使用 Scanner 类分配字母 å 的字符串不等于使用“正常”方式分配 å 的字符串: String a = "å" - 这是为什么?

import java.util.*;

public class UTF8Test {
public static void main(String [] args) {

    String [] Norge = {"løk", "hår", "vår", "sær", "søt"};

    Scanner input = new Scanner(System.in);

    String  test = input.nextLine();  //I enter løk here
    System.out.println(test);
    System.out.println(Norge[0]);

    for(int i = 0; i < Norge.length; i++) {
        if(Norge[i].equals(test) ) {
            System.out.println("YES!!");
        }
    }
}
}

编译器会显示这个:

l├©k

【问题讨论】:

  • 您究竟在哪里确保来自System.in 的字符是使用UTF-8 输入和解释的?我在代码中的任何地方都没有看到。因此,您的代码假设平台的默认字符集(由 Charset.defaultCharset() 标识)已经是 UTF-8。这是真的吗?
  • @BalusC 我没有确保 System.in 中的字符使用 UTF-8 进行解释。我该怎么做?
  • 另外,你用 3 行说“编译器显示这个”,但你列出的输出似乎与你的代码不匹配。
  • 取决于运行时环境。 ├© 作为 ø 的 mojibaked 形式表明原始环境使用 CP850 而不是 UTF-8。 CP850 默认用于 Windows 命令控制台。这表明您是在 Windows 命令控制台中运行它,而不是在 Eclipse 等支持 UTF-8 的 IDE 中运行。您应该能够通过打印/检查Charset.defaultCharset() 的结果来确认这一点。
  • 编译器在运行时/输入/输出期间根本不起任何作用。编译器仅在将.java 文件转换为.class 文件时起作用。

标签: java utf-8


【解决方案1】:

假设您的唯一要求是能够使用UTF8Test 类名所指示的UTF-8 任何地方,那么您的主要错误是您使用Windows 命令控制台来编译和运行你的 Java 程序。 ├© as mojibaked 形式的ø 即强烈建议您使用CP850 编码来编译Java 源代码文件。作为证据,在支持 UTF-8 的环境中运行它:

System.out.println(new String("ø".getBytes("UTF-8"), "CP850"));

这会打印出├©。这反过来强烈表明您正在使用 Windows 命令控制台来编译您的 Java 源代码文件,因为这是目前唯一默认使用 CP850 的常用环境。但是,Windows 命令控制台支持 UTF-8。

当您在文本编辑器中使用 UTF-8 编码保存(从字符转换为字节)源代码文件时,ø 字符将转换为字节 0xC30xB8(作为证据,请参阅"UTF-8 (hex)" entry in U+00F8 character info)。当您运行javac UTF8Test.java 时,基本上使用CP850 编码读取UTF-8 保存的源代码文件(从字节转换为字符)。字节0xC30xB8 在此编码中表示字符©(作为证据,请参见CP850 codepage layout)。这完全解释了您最初的问题。

没错,您可以通过-encoding UTF-8 参数指示javac 使用UTF-8 读取源代码文件。但是,Windows 命令控制台本身根本不支持 UTF-8 风格的输入和输出。当您使用 -encoding UTF-8 重新编译时,您仍然会得到 mojibaked 输出,因为命令控制台无法正确表示 UTF-8 输出。我在这里试了一下,我得到了一个学位符号:

乐克 l°k

如果您打算在任何地方都使用 UTF-8,并且想要坚持使用 Windows 命令控制台作为输入/输出环境,则此问题无法解决。基本上,您需要一个支持 UTF-8 的输入/输出环境。像 Eclipse 和 Netbeans 这样的 IDE 就是这样。或者,如果您打算将其作为支持 UTF-8 的独立程序运行,则应优先使用 Swing UI,而不是无 GUI 的控制台程序。

【讨论】:

  • "如果您打算将其作为独立程序运行,则应优先使用 Swing UI,而不是无 GUI 控制台程序。"不是这样。任何可以是无 gui 控制台程序的东西都应该。如果你想要 GUI,那么编写第二个程序,将 GUI 输入提供给第一个程序公开的 API。
  • 比我的答案更详细、更易于理解。它仍然归结为相同,但我更喜欢你的:-)
  • @Ingo:不,Windows 代码页 65001 通常不适用于控制台窗口。控制台窗口可能会任意吞下不想要的字符之后的输出。而且输入根本不起作用。
【解决方案2】:

如果你想要一个带有特殊字符的字符串文字,你可以尝试使用 Unicode 转义:

String [] Norge = {"l\u00F8k", "h\u00E5r", "v\u00E5r", "s\u00E6r", "s\u00F8t"};

虽然在源代码中包含特殊字符并没有错(至少在 java 中),但在某些情况下可能会导致编辑器、编译器或终端配置不当;我个人尽可能避免使用特殊字符。

顺便说一句,您还可以在 java 源代码的其他地方使用 Unicode 转义,包括 javadoc cmets 以及类、方法和变量名。

如果您从命令行编译,您可以使用-encoding 选项和UTF-8 作为其参数,将编译器配置为接受UTF-8。像这样:

javac -encoding UTF-8 ...

您可能还会发现这个问题很有用:Special Character in Java


您可以考虑将externalizing the strings 作为解决问题的替代方法。 Eclipse 提供了一种自动执行此操作的方法,但它基本上只是获取所有文字字符串,将它们放在单独的文件中,然后从该文件中读取以获取适当的字符串。这还允许您创建程序的翻译,方法是制作一个包含所有字符串翻译的不同文件,或者重新配置应用程序消息而无需重新编译。


编辑:我只是尝试自己编译和运行它(在 Eclipse 中),我没有遇到你提到的问题。因此,您的特定设置可能存在问题。

当我重新配置它以将代码编译为 US-ASCII 时,它两次都输出 l?k

当我重新配置它以将代码编译为 UTF-8 时,输出为 løkløk

当我将其编译为 UTF-16 时,输出为 þÿ l ø kløk,但是我无法从终端复制 þÿ l ø k 中的空格:它可以让我复制前两个,但离开剩下的。这可能与您遇到的问题有关 - 它们可能是一些控制字符在您的情况下搞砸了。

【讨论】:

  • OP 的具体问题不是由错误保存的源代码文件引起的。此外,这已经不是 1990 年了。现代编辑器使用 UTF-8 保存源代码文件。你还没有回答具体的问题。
  • @BalusC 这可能是由它引起的,你永远不知道。字符串外部化仍然很好。
【解决方案3】:

默认情况下,在 Windows 上,java 编译器使用“平台默认编码”解释其所有源文件。根据您运行编译器的环境,这可能是 ISO-8859-1、CP1252、UTF-8 或任何其他编码。

如果您使用的编辑器实际上是使用 UTF-8 对您的 java 源文件进行编码,但编译器正在使用另一种编码方式读取这些源文件,那么您的所有硬编码字符串的内容可能会被搞砸(正如您所经历的那样)。要解决此问题,请确保将 java 源文件保存为“平台默认编码”,或设置 java 编译器以将源文件解释为 UTF-8。

尝试使用javac -encoding UTF-8 UTF8Test.java 调用您的编译器。如有必要,请确保将 UTF-8 替换为编辑器用来保存源文件的任何内容。

【讨论】:

  • ø 的 ISO-8859-1-mojibaked 变体是 ø。但是,OP 得到了├©。所以你的答案基本上是错误的。证据:System.out.println(new String("ø".getBytes("UTF-8"), "ISO-8859-1"));(在支持 UTF-8 的环境中执行此操作!)
  • 好吧,如果这个人使用的是挪威代码页,他实际上可能使用的是 ISO-8859-4 或 ISO-8859-10。我不确定这些会如何翻译,但我仍然认为这是可能的。
  • 抱歉,2 字节 UTF-8 字符的任何 ISO-8859-X mojibaked 变体都以 Ã (0xC3) 开头
  • 哦,所以你认为另一边的编码是错误的?如果是这样的话,Norge[0] 不会是正确打印的那个。我相信 System.out 确实使用默认的平台字符集,不是吗?或者是 Windows 命令提示符特别愚蠢并且使用不同于系统其余部分的编码,并且无法处理 java 打印到它的任何内容?
  • @BalusC:我已经稍微编辑了我的答案,以删除对错误编码的引用。现在似乎更正确?不过这个概念还是一样的。
【解决方案4】:

如果您在 Eclipse 中工作,请更改控制台编码,使用 运行菜单>运行配置..>通用选项卡(右侧)>在编码面板中>选择Other=UTF-8


【讨论】:

    【解决方案5】:

    我在显示挪威字符时遇到问题。尝试使用编码:ISO 8859- 10

    【讨论】:

    • 这听起来不相关,因为 OP 想要使用 UTF-8。
    猜你喜欢
    • 2017-05-18
    • 2011-10-29
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 2011-11-13
    • 2023-03-11
    • 2021-04-19
    相关资源
    最近更新 更多