通过此例可以看出,从ISO-8859-1字符集转换成Unicode字符集的过程是将字节化字符数据中的每个一个byte类型元素直接保存成一个char类型元素。也就是说下面的代码:
byte[] bytes = { (byte) 0x61, (byte) 0x62, (byte) 0x63 };
String str = new String(bytes, Charset.forName("ISO-8859-1"));
byte[] bytes = { (byte) 0x61, (byte) 0x62, (byte) 0x63 };
String str = new String(bytes, Charset.forName("ISO-8859-1"));
等效于:
byte[] bytes = { (byte) 0x61, (byte) 0x62, (byte) 0x63 };
char[] tmp = new char[bytes.length];
for (int i=0; i
tmp[i] = (char)bytes[i];
}
String str = new String(tmp);
byte[] bytes = { (byte) 0x61, (byte) 0x62, (byte) 0x63 };
char[] tmp = new char[bytes.length];
for (int i=0; i
tmp[i] = (char)bytes[i];
}
String str = new String(tmp);
需要注意的是,ISO-8859-1到Unicode的转换过程是对编码值为0x00 - 0xFF之间都有效的一种转换。在ISO-8859-1字符集中,0x00-0x1F、0x7F、0x80-0x9F没有定义。我们可以使用其中几个无效编码进行测试:
view plaincopy to clipboardprint?
public static void main(String[] args) {
// 无效的ISO-8859-1编码
byte[] bytes = { (byte) 0x00, (byte) 0x1A, (byte) 0x7F, (byte) 0x93 };
String str = new String(bytes, Charset.forName("ISO-8859-1"));
printBytes("ISO-8859-1编码:", str.getBytes(Charset.forName("ISO-8859-1")));
printBytes("UNICODE编码:", str.getBytes(Charset.forName("UNICODE")));
}
public static void printBytes(String title, byte[] data) {
// 同上
}
public static void main(String[] args) {
// 无效的ISO-8859-1编码
byte[] bytes = { (byte) 0x00, (byte) 0x1A, (byte) 0x7F, (byte) 0x93 };
String str = new String(bytes, Charset.forName("ISO-8859-1"));
printBytes("ISO-8859-1编码:", str.getBytes(Charset.forName("ISO-8859-1")));
printBytes("UNICODE编码:", str.getBytes(Charset.forName("UNICODE")));
}
public static void printBytes(String title, byte[] data) {
// 同上
}
上例的输出结果为:
ISO-8859-1编码:
0x00 0x1A 0x7F 0x93
UNICODE编码:
0xFE 0xFF 0x00 0x00 0x00 0x1A 0x00 0x7F 0x00 0x93
根据这一特点,我们可以总结出最后一个要点:
利用ISO-8859-1字符集,我们可以将任何一个字节数组无损保存到字符串对象中。
也就是说,可以利用这一特点将字节化字符数据的原始字节数据(而不是经过Unicode字符集转换之后的数据)直接保存在字符串对象中。反之也可以从一个经过ISO-8859-1编码的字符串对象中取出原始字节数据。例如:
view plaincopy to clipboardprint?
public static void main(String[] args) {
byte[] utf8Bytes = {(byte)0xE4, (byte)0xB8, (byte)0xAD, (byte)0xE5, (byte)0x9B, (byte)0xBD};
printBytes("原始字节流:" , utf8Bytes);
// ISO-8859-1编码过程
// 保存原始字节数据流(不经过Unicode编码)到字符串对象
String isoStr = new String(utf8Bytes, Charset.forName("ISO-8859-1"));
// ISO-8859-1解码过程
// 从字符串对象中取得与utf8Bytes内容完全相等的原始字节数据流
byte[] tmp = isoStr.getBytes(Charset.forName("ISO-8859-1"));
printBytes("转换字节流:" , tmp);
}
public static void printBytes(String title, byte[] data) {
// 同上
}
public static void main(String[] args) {
byte[] utf8Bytes = {(byte)0xE4, (byte)0xB8, (byte)0xAD, (byte)0xE5, (byte)0x9B, (byte)0xBD};
printBytes("原始字节流:" , utf8Bytes);
// ISO-8859-1编码过程
// 保存原始字节数据流(不经过Unicode编码)到字符串对象
String isoStr = new String(utf8Bytes, Charset.forName("ISO-8859-1"));
// ISO-8859-1解码过程
// 从字符串对象中取得与utf8Bytes内容完全相等的原始字节数据流
byte[] tmp = isoStr.getBytes(Charset.forName("ISO-8859-1"));
printBytes("转换字节流:" , tmp);
}
public static void printBytes(String title, byte[] data) {
// 同上
}
上例的输出结果为:
原始字节流:
0xE4 0xB8 0xAD 0xE5 0x9B 0xBD
转换字节流:
0xE4 0xB8 0xAD 0xE5 0x9B 0xBD
这种通过字符串对象保存原始字节数据的方法被很多地方所使用。最常见的就是Java WEB应用中Web服务器对来自于服务器的表单数据的处理,关于这方面的详细说明请参考 如何解决Java WEB应用中的乱码问题。