2015-07-06 32 views
0

的字符串改变我已经以下代码:java的UTF-8编码字节为奇数个字符

public static void main(String args[]) throws UnsupportedEncodingException { 
    System.setProperty("file.encoding", "gbk"); 

    String name = "こんにちわ"; 
    String copy = new String(name.getBytes("utf-8")); 

    byte[] b1 = name.getBytes("utf-8"); 
    byte[] b2 = copy.getBytes(); 

    System.out.println("b1: " + Arrays.toString(b1)); 
    System.out.println("b2: " + Arrays.toString(b2)); 
} 

控制台输出是:

B1:[-29,-127, - 109,-29,-126,-109,-29,-127,-85,-29,-127,-95,-29,-126,-113]
b2:[-29,-127 ,-109,-29,-126,-109,-29,-127,-85,-29,-127,-95,-29,-126,]

注意新字符串中最后一个字节不同。


现在,如果我使用输入String name = "こんにち";(仅4日本汉字),相反,它更改为:

B1:[-29,-127,-109,-29,-126 ,-109,-29,-127,-85,-29,-127,-95]
b2:[-29,-127,-109,-29,-126,-109,-29,-127 ,-85,-29,-127,-95]

这次字节完全一样。


我用java jdk1.6.0_45的窗口。默认字符集是gbk。 我遇到过一些编码限制吗?

+2

什么是您的设置默认字符集? – RealSkeptic

+1

我在两行上都得到''-113“',在窗口上使用1.6.0_45。 – Keppil

+0

@RealSkeptic默认字符集是gbk – oyss

回答

2

基本上,你的程序的前四行等效于:

String name = "こんにちわ"; 
    byte[] b1 = name.getBytes("utf-8"); 

    String a = new String(name.getBytes("utf-8"), "gbk"); 
    byte[] b2 = a.getBytes("gbk"); 

也就是说,你正在服用的字节数组(b1)这是你的日语字符串的UTF-8表示,以及告知Java“这个字节数组采用GBK编码,将其转换为文本”。

这不起作用,如果你打印你的a字符串,你会发现它不会打印日文文本,而是打印一些中文乱码 - 最后加上替换字符(“ ”)。

在内部,Java字符串以UTF-16编码。但是当你转换成字节数组和从字节数组转换时,你必须指定编码。编码彼此不同,并且可以使用相同的字节值或字节值序列来表示完全不同的字符。

而在这种情况下,UTF-8中存在的字节序列在GBK中是不合法的,因此Java将用替换字符替换它们。

如果要从b1创建一个新字符串,并且该字符串仍然是こんにちわ,则需要创建a以告知Java该字节为UTF-8。

String a = new String(name.getBytes("utf-8"), "utf-8"); 

然后,你a将等于name

然后,如果你只是做a.getBytes(),你会得到代表该字符串的字节在GBK。这将是不同b1,因为它是在不同的编码。要获得相同的数组,您需要使用相同的编码(a.getBytes("utf-8"))。

  • 尽量不要依赖Java的默认字符集。从字符串获取字节时以及在将字节转换为字符串时,始终指定确切的字符集。
  • 不同的字符集为同一个字符串生成不同的字节数组。
  • getBytes()String(byte[])没有字符集参数不给你真实的字节序列,String的基础。他们使用JVM的默认字符集 - 在你的情况下,GBK。
+0

我试过“new String(name.getBytes(”utf-8“),”utf-8“)”;但它给了我这样的字节。 “-92”“ - 77”“ - 92”“ - 13”“ - 92”“ - 53”“ - 92”“ - 17”“ - 92”“ - 17”与“こんにわわ”完全不同。的getBytes( “UTF-8”)。这些字节用于散列,因此它们需要在字节中完全相同以产生相同的散列号。 – oyss

+0

你有没有看到我说:“要获得相同的数组,你需要使用相同的编码('a.getBytes(”utf-8“)')”? – RealSkeptic

+0

错过了这个部分。现在没问题。谢谢。 – oyss

1

您正面临一个常见问题,您正在使用默认平台编码,其编码字节顺序不同。 此行

byte[] b1 = name.getBytes("utf-8"); 

字符串转换您使用UTF-8编码字节[]。 这条线:

String a = new String(name.getBytes("utf-8")); 

创建从字节数组的字符串,但没有指定的字符集。这可能是一个问题,因为jvm“拿起它自己的价值”;请注意,String类还具有以下的构造:

String(byte[] bytes, Charset charset) 

,允许你指定如何使用您作为第二个参数传递的编码,以创建从字节序列的字符串。

String a = new String(name.getBytes("utf-8"));正在使用默认平台,从您的评论读取,是gbk。 所以你真正做的是:

String a = new String(name.getBytes("utf-8"),"gbk"); 

,而不是

String a = new String(name.getBytes("utf-8"),"UTF-8"); 

的“刁钻”的部分是,一些编码重叠他们将一些(但不是全部)符号与相同的字节序列;所以它们以某种方式表示一些字符串,但其他字符以不同的方式表示。例如,ISO8859-1代表的字符与ISO8859-15相同,除了欧元和其他一些字符(引入ISO8859-15的单字节包含欧元符号,您可以看到差异here),所以如果字符串不包含€符号,则表示字符串的序列在ISO8859-1和ISO8859-15中相同。

如果你喜欢阅读与Java编码也与XML的东西,你可以看看this one

1

不,你不符合编码的限制,但你的代码通过可变ab2

使用默认字符集

试试这个:

String a = new String(name.getBytes("UTF-8"),"UTF-8"); 
    byte[] b2 = a.getBytes("UTF-8"); 
相关问题