今天又研究了一下字符编码。写了些测试代码,算是比较了解了。
     主要是研究 iso-8859-1
     
     建议先看这篇:《第二篇:JAVA字符编码系列二:Unicode,ISO-8859-1,GBK,UTF-8编码及…》
     
     http://my.oschina.net/whp/blog/36846
     然后再看看 iso-8859-1 的定义。
     
     http://baike.baidu.com/view/2613676.htm
     
      
      这一句话非常关键:
      
      因为ISO-8859-1编码范围使用了单字节内的所有空间,在支持ISO-8859-1的系统中传输和存储其他任何编码的字节流都不会被抛弃。换言之,把其他任何编码的字节流当作ISO-8859-1编码看待都没有问题。这是个很重要的特性,MySQL数据库默认编码是Latin1就是利用了这个特性。
      在工作中,从 web 提交的数据,到了 web 容器后,变成了 iso-8859-1 的字符串。
      
      可以认为,被执行了如下代码:
      
      byte[] buf_gbk = s.getBytes(“gbk”);
      
      String sIso88591 = new String(buf_gbk, “iso-8859-1”);
      所以,我们获取数据时需要执行:
      
      byte[] buf_iso88591 = sIso88591.getBytes(“iso-8859-1”);
      
      String sGbk = new String(buf_iso88591, “gbk”);
      将编码转回 gbk。
     
    
   
    
     
      我们本应该用
     
     
      gbk
     
     
      的编码来读取数据并解码成字符串,但结果却采用了ISO-8859-1的编码,导致生成一个错误的字符串。要恢复,就要先把字符串恢复成原始字节数组,然后通过正确的编码
     
     
      gbk
     
     
      再次解码成字 符串(即把以
     
     
      gbk
     
     
      编码的数据转成unicode的字符串)。注意,
      
       jvm中的字符串永远都是unicode编码的
      
      。
      
      但编码转换并不是负负得正那么简单,这里我们之所以可以正确地转换回来,是因为 ISO8859-1 是单字节编码,所以每个字节被按照原样转换为String ,也就是说,虽然这是一个错误的转换,但编码没有改变,所以我们仍然有机会把编码转换回来!
     
看完这两篇后,写了段测试代码:
- 
      
 
 package
 
 
 com.fsti.enc;
 
 
- 
      
 
- 
      
 
 public
 
 
 
 
 class
 
 
 EncUtil {
 
 
- 
      
 
- 
      
 
 public
 
 
 
 
 static
 
 
 String getHex(
 
 
 byte
 
 
 b)
 
 
- 
      
 {
 
- 
      
 String hex = Integer.toHexString(b &
 
 0xff
 
 
 );
 
 
- 
      
 
 if
 
 
 (hex.length()==
 
 
 1
 
 
 )
 
 
- 
      
 {
 
- 
      
 hex =
 
 “0”
 
 
 + hex;
 
 
- 
      
 }
 
- 
      
 
 return
 
 
 hex;
 
 
- 
      
 }
 
- 
      
 
- 
      
 
 public
 
 
 
 
 static
 
 
 
 
 void
 
 
 showBytes(
 
 
 byte
 
 
 [] buffer)
 
 
- 
      
 {
 
- 
      
 
 for
 
 
 (
 
 
 int
 
 
 i=
 
 
 0
 
 
 ; i<buffer.length; i++)
 
 
- 
      
 {
 
- 
      
 System.out.print( getHex(buffer[i]) +
 
 ” ”
 
 
 );
 
 
- 
      
 }
 
- 
      
 System.out.println();
 
- 
      
 
- 
      
 }
 
- 
      
 
- 
      
 
 public
 
 
 
 
 static
 
 
 
 
 void
 
 
 showChar(String s)
 
 
- 
      
 {
 
- 
      
 
 for
 
 
 (
 
 
 int
 
 
 i=
 
 
 0
 
 
 ; i<s.length(); i++)
 
 
- 
      
 {
 
- 
      
 System.out.print( getHex((
 
 byte
 
 
 )(s.charAt(i))) +
 
 
 ” ”
 
 
 );
 
 
- 
      
 }
 
- 
      
 System.out.println();
 
- 
      
 
- 
      
 }
 
- 
      
 
- 
      
 }
 
- 
      
 
 package
 
 
 com.fsti.enc;
 
 
- 
      
 
- 
      
 
- 
      
 
 /**
 
 
- 
      
 
 * http://baike.baidu.com/view/2613676.htm
 
 
- 
      
 
 * @author zch
 
 
- 
      
 
 * @date Apr 20, 2012
 
 
- 
      
 
 *
 
 
- 
      
 
 */
 
 
 
 
- 
      
 
 public
 
 
 
 
 class
 
 
 Test_Iso8859_1
 
 
 extends
 
 
 EncUtil{
 
 
- 
      
 
 public
 
 
 
 
 static
 
 
 String s =
 
 
- 
      
 
 “http://baike.baidu.com/view/2613676.htm\r\n”
 
 
 +
 
 
- 
      
 
 “ ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,”
 
 
 +
 
 
- 
      
 
 “0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。”
 
 
 +
 
 
- 
      
 
 “ISO-8859-1收录的字符除ASCII收录的字符外,还包括西欧语言、希腊语、泰语、阿拉伯语、希伯来语”
 
 
 +
 
 
- 
      
 
 “对应的文字符号。欧元符号出现的比较晚,没有被收录在ISO-8859-1当中。\r\n”
 
 
 +
 
 
- 
      
 
 “ 因为ISO-8859-1编码范围使用了单字节内的所有空间,在支持ISO-8859-1的系统中传输和存储其他任何”
 
 
 +
 
 
- 
      
 
 “编码的字节流都不会被抛弃。换言之,把其他任何编码的字节流当作ISO-8859-1编码看待都没有问题。这是”
 
 
 +
 
 
- 
      
 
 “个很重要的特性,MySQL数据库默认编码是Latin1就是利用了这个特性。ASCII编码是一个7位的容器,”
 
 
 +
 
 
- 
      
 
 “ISO-8859-1编码是一个8位的容器。\r\n”
 
 
 +
 
 
- 
      
 
 “ Latin1是ISO-8859-1的别名,有些环境下写作Latin-1。”
 
 
 ;
 
 
- 
      
 
- 
      
 
 public
 
 
 
 
 static
 
 
 
 
 void
 
 
 testChar(
 
 
 char
 
 
 c)
 
 
 throws
 
 
 Exception
 
 
- 
      
 {
 
- 
      
 
 //char c = ‘中’;
 
 
 
 
- 
      
 System.out.println( c );
 
- 
      
 System.out.println( (
 
 int
 
 
 )c );
 
 
- 
      
 System.out.println( Integer.toHexString(c) );
 
- 
      
 
 if
 
 
 (c>
 
 
 255
 
 
 )
 
 
- 
      
 {
 
- 
      
 
 byte
 
 
 low = (
 
 
 byte
 
 
 )(c /
 
 
 256
 
 
 );
 
 
- 
      
 
 byte
 
 
 hight = (
 
 
 byte
 
 
 )(c %
 
 
 256
 
 
 );
 
 
- 
      
 System.out.println( getHex(low) );
 
- 
      
 System.out.println( getHex(hight) );
 
- 
      
 }
 
- 
      
 }
 
- 
      
 
- 
      
 
 public
 
 
 
 
 static
 
 
 
 
 void
 
 
 testString()
 
 
 throws
 
 
 Exception
 
 
- 
      
 {
 
- 
      
 
 for
 
 
 (
 
 
 int
 
 
 i=
 
 
 0
 
 
 ; i<s.length(); i++)
 
 
- 
      
 {
 
- 
      
 testChar(s.charAt(i));
 
- 
      
 }
 
- 
      
 }
 
- 
      
 
- 
      
 
- 
      
 
 public
 
 
 
 
 static
 
 
 
 
 void
 
 
 testString_02()
 
 
 throws
 
 
 Exception
 
 
- 
      
 {
 
- 
      
 
- 
      
 StringBuffer sb =
 
 new
 
 
 StringBuffer();
 
 
- 
      
 
 for
 
 
 (
 
 
 int
 
 
 i=
 
 
 0
 
 
 ; i<s.length(); i++)
 
 
- 
      
 {
 
- 
      
 
 char
 
 
 c = s.charAt(i);
 
 
- 
      
 
 if
 
 
 (c>
 
 
 255
 
 
 )
 
 
- 
      
 {
 
- 
      
 
 char
 
 
 hight = (
 
 
 char
 
 
 )(c /
 
 
 256
 
 
 );
 
 
- 
      
 
 char
 
 
 low = (
 
 
 char
 
 
 )(c %
 
 
 256
 
 
 );
 
 
- 
      
 sb.append(hight);
 
- 
      
 sb.append(low);
 
- 
      
 }
 
- 
      
 
 else
 
 
 
 
- 
      
 {
 
- 
      
 sb.append(c);
 
- 
      
 }
 
- 
      
 }
 
- 
      
 String sIso88591 = sb.toString();
 
- 
      
 System.out.println(sIso88591);
 
- 
      
 
- 
      
 
 byte
 
 
 [] buf = sIso88591.getBytes(
 
 
 “iso-8859-1”
 
 
 );
 
 
- 
      
 showBytes(buf);
 
- 
      
 String sUtf_8 =
 
 new
 
 
 String(buf,
 
 
 “gbk”
 
 
 );
 
 
- 
      
 System.out.println(sUtf_8);
 
- 
      
 }
 
- 
      
 
- 
      
 
 public
 
 
 
 
 static
 
 
 
 
 void
 
 
 testString_03()
 
 
 throws
 
 
 Exception
 
 
- 
      
 {
 
- 
      
 System.out.println(
 
 “s:”
 
 
 + s);
 
 
- 
      
 
- 
      
 
 byte
 
 
 [] buf_gbk = s.getBytes(
 
 
 “gbk”
 
 
 );
 
 
- 
      
 System.out.println(
 
 “buf_gbk:”
 
 
 );
 
 
- 
      
 showBytes(buf_gbk);
 
- 
      
 
- 
      
 StringBuffer sb =
 
 new
 
 
 StringBuffer();
 
 
- 
      
 
 for
 
 
 (
 
 
 int
 
 
 i=
 
 
 0
 
 
 ; i<buf_gbk.length; i++)
 
 
- 
      
 {
 
- 
      
 
 char
 
 
 c = (
 
 
 char
 
 
 )buf_gbk[i];
 
 
- 
      
 sb.append( c );
 
- 
      
 System.out.println(c +
 
 “:”
 
 
 + getHex((
 
 
 byte
 
 
 )c));
 
 
- 
      
 }
 
- 
      
 
- 
      
 String sIso88591 = sb.toString();
 
- 
      
 System.out.println(
 
 “sIso88591:”
 
 
 );
 
 
- 
      
 System.out.println(sIso88591);
 
- 
      
 System.out.println(
 
 “showChar(sIso88591):”
 
 
 );
 
 
- 
      
 showChar(sIso88591);
 
- 
      
 
- 
      
 
 byte
 
 
 [] buf_iso88591 = sIso88591.getBytes(
 
 
 “iso-8859-1”
 
 
 );
 
 
- 
      
 System.out.println(
 
 “buf_iso88591:”
 
 
 );
 
 
- 
      
 showBytes(buf_iso88591);
 
- 
      
 String sUtf_8 =
 
 new
 
 
 String(buf_iso88591,
 
 
 “gbk”
 
 
 );
 
 
- 
      
 System.out.println(sUtf_8);
 
- 
      
 
- 
      
 }
 
- 
      
 
- 
      
 
 public
 
 
 
 
 static
 
 
 
 
 void
 
 
 testString_04()
 
 
 throws
 
 
 Exception
 
 
- 
      
 {
 
- 
      
 System.out.println(
 
 “s:”
 
 
 + s);
 
 
- 
      
 
- 
      
 
 byte
 
 
 [] buf_gbk = s.getBytes(
 
 
 “gbk”
 
 
 );
 
 
- 
      
 System.out.println(
 
 “buf_gbk:”
 
 
 );
 
 
- 
      
 showBytes(buf_gbk);
 
- 
      
 
- 
      
 String sIso88591 =
 
 new
 
 
 String(buf_gbk,
 
 
 “iso-8859-1”
 
 
 );
 
 
- 
      
 
- 
      
 System.out.println(
 
 “sIso88591:”
 
 
 );
 
 
- 
      
 System.out.println(sIso88591);
 
- 
      
 System.out.println(
 
 “showChar(sIso88591):”
 
 
 );
 
 
- 
      
 showChar(sIso88591);
 
- 
      
 
- 
      
 
 byte
 
 
 [] buf_iso88591 = sIso88591.getBytes(
 
 
 “iso-8859-1”
 
 
 );
 
 
- 
      
 System.out.println(
 
 “buf_iso88591:”
 
 
 );
 
 
- 
      
 showBytes(buf_iso88591);
 
- 
      
 String sGbk =
 
 new
 
 
 String(buf_iso88591,
 
 
 “gbk”
 
 
 );
 
 
- 
      
 System.out.println(sGbk);
 
- 
      
 
- 
      
 }
 
- 
      
 
- 
      
 
 /**
 
 
- 
      
 
 * @param args
 
 
- 
      
 
 */
 
 
 
 
- 
      
 
 public
 
 
 
 
 static
 
 
 
 
 void
 
 
 main(String[] args)
 
 
 throws
 
 
 Exception{
 
 
- 
      
 
 //testString();
 
 
 
 
- 
      
 
 //testString_02();
 
 
 
 
- 
      
 testString_04();
 
- 
      
 }
 
- 
      
 
- 
      
 }
 
    参考资料:
    
    http://my.oschina.net/whp/blog/36846
    
    http://baike.baidu.com/view/2613676.htm
   
 

