考虑以下事项:
public static void main(String... strings) throws Exception {
byte[] b = { -30, -128, -94 };
//section utf-32
String string1 = new String(b,"UTF-32");
System.out.println(string1); //prints ?
printBytes(string1.getBytes("UTF-32")); //prints 0 0 -1 -3
printBytes(string1.getBytes()); //prints 63
//section utf-8
String string2 = new String(b,"UTF-8");
System.out.println(string2); // prints •
printBytes(string2.getBytes("UTF-8")); //prints -30 -128 -94
printBytes(string2.getBytes()); //prints -107
}
public static void printBytes(byte[] bytes){
for(byte b : bytes){
System.out.print(b + " " );
}
System.out.println();
}
输出:
?
0 0 -1 -3
63
•
-30 -128 -94
-107
所以我有两个问题:
getBytes()
和getBytes(charSet)
不同,即使我特别提到了字符串' s charset getByte
的两个字节输出都与实际的byte[] b
不同? (即如何将字符串转换回原始字节数组?)答案 0 :(得分:2)
问题1:
在两个部分中:为什么输出
getBytes()
和getBytes(charSet)
不同,即使我特别提到了字符串的字符集
您指定的字符集在字符串的字符编码期间用于字节数组(即仅在方法本身中)。它不是String
实例本身的一部分。您不设置字符串的字符集,不存储字符集。
Java没有字符集的内部字节编码;它在内部使用char
的数组。如果您在未指定字符集的情况下致电String.getBytes()
,则会使用平台默认 - 例如Windows机器上的Windows-1252。
问题2:
为什么utf-32部分中
getByte
的两个字节输出都与实际的byte[] b
不同? (即如何将字符串转换回原始字节数组?)
你不能总是这样做。并非所有字节都表示有效的字符编码。因此,如果这样的编码数组被解码,那么这些编码将被静默忽略,即简单地跳过这些字节。
这已在String string1 = new String(b,"UTF-32");
和String string2 = new String(b,"UTF-8");
期间发生。
您可以使用CharsetDecoder
的实例更改此行为,使用Charset.newDecoder
检索。
如果要将随机字节数组编码到String实例中,则应使用十六进制或base 64 编码器。你不应该使用字符解码器。
答案 1 :(得分:2)
Java String / char (16位UTF-16!) / Reader / Writer 用于Unicode文本。因此,所有脚本都可以组合成文本。
Java 字节(8位) / InputStream / OutputStream 用于二进制数据。如果该数据代表文本,则需要知道其编码以从中生成文本。
因此,从字节到文本的转换始终需要Charset。通常存在没有charset的重载方法,然后它默认为System.getProperty("file.encoding")
,它可以在每个平台上有所不同。
如果数据是跨平台的,则使用默认值是绝对不可移植的。
所以你误以为编码属于String。这是可以理解的,因为在C / C ++中,unsigned char和byte在很大程度上是可以互换的,并且编码成了一场噩梦。