在Java中,使用字节数组保存不同字符集的字符值,如使用ASCII字符集保存“abc”的方法如下:
// 使用ASCII编码的“abc”
byte[] ascBytes = {(byte)0x61, (byte)0x62, (byte)0x63};
// 使用ASCII编码的“abc”
byte[] ascBytes = {(byte)0x61, (byte)0x62, (byte)0x63};
使用GBK字符集保存“中国”二字的方法如下:
// 使用GBK编码的“中国”
byte[] gbkBytes = {(byte)0xD6, (byte)0xD0, (byte)0xB9, (byte)0xFA};
// 使用GBK编码的“中国”
byte[] gbkBytes = {(byte)0xD6, (byte)0xD0, (byte)0xB9, (byte)0xFA};
当然我们也可以使用Unicode字符集保存“中国”二字。如:
// 使用Unicode编码的“中国”
byte[] unicodeBytes = {(byte)0x4E, (byte)0x2D, (byte)0x56, (byte)0xFD};
// 使用Unicode编码的“中国”
byte[] unicodeBytes = {(byte)0x4E, (byte)0x2D, (byte)0x56, (byte)0xFD};
一个特殊的字符集UTF-8是与Unicode规范对应的多字节表示的字符集。如“中”字的UTF-8编码为“0xE4, 0xB8, 0xAD”三个字节。
在这里,将这些与具体字符集相对应的字节化的数据流称为字节化字符数据,与字符串对象形成鲜明对照的是,字符串对象的最小单位是两个字节而字节化字符数据的最小单位则是一个字节。由此我们可以明确另外两个要点:
字节化字符数据中的每一个元素始终占据一个字节长度,一个或多个元素表示一个字符。
字节化字符数据必须与一个字符集相对应。
字节化字符数据与字符串对象的互换
在Java程序运行过程中,字符串对象始终以Unicode编码方式保存在内存中,但将字符串对象保存到持久化资源(文件或数据库)或将其通过网络传输时,通常是以字节化字符数据的方式进行处理。这样就要求Java API必须提供两者互换的功能。事实上这一功能在String类及Charset类中已经提供。
一方面我们可以利用String类的getBytes()方法返回不同字符集的字节化字符数据,其本质是从Unicode字符集编码向其它字符集编码转换的过程。例如:
view plaincopy to clipboardprint?
public static void main(String[] args) {
String str = "中国";
printBytes("中国的UNICODE编码:", str.getBytes(Charset.forName("unicode")));
printBytes("中国的GBK编码:", str.getBytes(Charset.forName("GBK")));
printBytes("中国的UTF-8编码:", str.getBytes(Charset.forName("UTF-8")));
}
public static void printBytes(String title, byte[] data) {
System.out.println(title);
for (byte b : data) {
System.out.print("0x" + toHexString(b) + " ");
}
System.out.println();
}
public static String toHexString(byte value) {
String tmp = Integer.toHexString(value & 0xFF);
if (tmp.length() == 1) {
tmp = "0" + tmp;
}
return tmp.toUpperCase();
}
public static void main(String[] args) {
String str = "中国";
printBytes("中国的UNICODE编码:", str.getBytes(Charset.forName("unicode")));
printBytes("中国的GBK编码:", str.getBytes(Charset.forName("GBK")));
printBytes("中国的UTF-8编码:", str.getBytes(Charset.forName("UTF-8")));
}
public static void printBytes(String title, byte[] data) {
System.out.println(title);
for (byte b : data) {
System.out.print("0x" + toHexString(b) + " ");
}
System.out.println();
}
public static String toHexString(byte value) {
String tmp = Integer.toHexString(value & 0xFF);
if (tmp.length() == 1) {
tmp = "0" + tmp;
}
return tmp.toUpperCase();
}
上例的输出结果为:
中国的UNICODE编码:
0xFE 0xFF 0x4E 0x2D 0x56 0xFD
中国的GBK编码:
0xD6 0xD0 0xB9 0xFA
中国的UTF-8编码:
0xE4 0xB8 0xAD 0xE5 0x9B 0xBD
需要注意的是,从字符串对象中取出的Unicode编码的字节化字符数据时,其开始部分存在一个BOM(ByteOrderMark),一般情况下,该BOM值为“0xFE 0xFF”,即大端字节序(BIG_ENDIAN)。如果BOM值为“0xFF 0xFE”则为小端字节序(LITTLE_ENDIAN)。