Java UTF-8奇怪的行为

时间:2009-08-13 13:41:49

标签: java utf-8

我正在尝试用Java解码一些UTF-8字符串。 这些字符串包含一些组合的unicode字符,例如CC 88(组合diaresis)。 根据{{​​3}}

,字符序列似乎没问题

但转换为String后的输出无效。 有什么想法吗?

byte[] utf8 = { 105, -52, -120 };
System.out.print("{{");
for(int i = 0; i < utf8.length; ++i)
{
    int value = utf8[i] & 0xFF;
    System.out.print(Integer.toHexString(value));
}
System.out.println("}}");
System.out.println(">" + new String(utf8, "UTF-8"));

输出:

    {{69cc88}}
    >i?

4 个答案:

答案 0 :(得分:9)

您输出的控制台(例如Windows)可能不支持unicode,并且可能会破坏字符。控制台输出不是数据的良好表示。

尝试将输出写入文件,确保FileWriter上的编码正确,然后在unicode友好的编辑器中打开文件。

或者,使用调试器确保字符符合您的预期。只是不要相信控制台。

答案 1 :(得分:4)

代码很好,但正如skaffman所说,你的控制台可能不支持相应的角色。

要进行测试,您需要打印出字符的unicode值:

public class Test {
    public static void main(String[] args) throws Exception {
        byte[] utf8 = { 105, -52, -120 };
        String text = new String(utf8, "UTF-8");
        for (int i=0; i < text.length(); i++) {
            System.out.println(Integer.toHexString(text.charAt(i)));
        }
    }
}

这打印69,308 - correct(U + 0069,U + 0308)。

答案 2 :(得分:4)

你是对的。谢谢!!

这里我最终在Windows上的Eclipse中解决了这个问题:

  • 在“运行配置,参数”选项卡中,我向“VM参数”添加了“-Dfile.encoding=UTF-8
  • 在运行配置,公共选项卡中,我将控制台编码设置为UTF-8

我修改了代码如下:

byte[] utf8 = { 105, -52, -120 };
System.out.print("{{");
for(int i = 0; i < utf8.length; ++i)
{
    int value = utf8[i] & 0xFF;
    System.out.print(Integer.toHexString(value));
}
System.out.println("}}");

PrintStream sysout = new PrintStream(System.out, true, "UTF-8");
sysout.print(">" + new String(utf8, "UTF-8"));

输出:

{{69cc88}}
> ï

谢谢!

答案 3 :(得分:1)

Java在将它们写入stdout之前,将Unicode字符编码为本机系统编码的字节,并非不合理。某些操作系统,如许多Linux发行版,使用UTF-8作为默认字符集,这很不错。

由于各种向后兼容性原因,Windows上的情况有所不同。默认的系统编码将是“ANSI”代码页之一,如果您打开默认命令提示符(cmd.exe),它将是旧的“OEM”DOS代码页之一(尽管它是可以在那里获得ANSI和Unicode {。{3}}。

由于U + 0308不在任何“ANSI”字符集中(在您的情况下可能为with a bit of work),因此它将被编码为错误字符(通常是问号)。

Unicode启用一切的替代方法是1252组合序列U + 0069 U + 0308到单个字符U + 00EF:

  public static void emit(String foo) throws IOException {
    System.out.println("Literal: " + foo);
    System.out.print("Hex: ");
    for (char ch : foo.toCharArray()) {
      System.out.print(Integer.toHexString(ch & 0xFFFF) + " ");
    }
    System.out.println();
  }

  public static void main(String[] args) throws IOException {
    String foo = "\u0069\u0308";
    emit(foo);
    foo = Normalizer.normalize(foo, Normalizer.Form.NFC);
    emit(foo);
  }

windows-1252下,此代码将发出:

Literal: i?
Hex: 69 308 
Literal: ï
Hex: ef