字符(串)与unicode转换

http://ccchhhlll1988-163-com.iteye.com/blog/1401363

昨天在公司听见同事在询问中文与asicii码如何转换?我当时就很差异,asicii码怎么可能表示中文啊?!原来是要将形如\uXXXX(X表示一16进制数,非X)的码与中文转换。好吧,我刚知道“这竟然被叫成asicii码”! 

于是现在网上找了一下资料,对参考的代码进行了一些优化,如StringBuffer的使用和正则表达式验证合法性。 
通过思考,已经能理解Unicode向字符的转换,对相反的转换的原理基本理解,还需要查查原理。 

基本理论: 
Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。目前6.0版本已经发布。Unicode定义了大到足以代表人类所有可读字符的字符集。Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。 
Unicode的实现方式有UTF-8、UTF-16、UTF-32。 
UTF-8以字节为单位对Unicode进行编码,对不同范围的字符使用不同长度的编码。 
UTF-16编码以16位无符号整数为单位。 
UTF-32编码以32位无符号整数为单位。Unicode的UTF-32编码就是其对应的32位无符号整数。 

形如\u1234的unicode应是采取utf-16的实现方式,所以以下encode方法中先将字符用utf-16方式表示,将每8bit放入byte中,然后将byte转为16进制表示,4个16进制符号就表示一个字符的unicode编码了。 

其中与0xff的与运算和删除符号表示两个步骤都是必须的。 
1,不进行0xff与,然后输出bytesUtf16[n],感觉诧异,byte不就8bit吗,怎么存输出2+个16位符号?后两个符号是需要的,所以有了&操作。后来理解,因为符号引起的前方补位。-的前补1,16制后前全为f,+补0,16制后仍是byte的16制。所以这里需要与0xff,致使只剩下后8位。也就是编码需要的。 
2,Unicode标准建议用BOM(Byte Order Mark)来区分字节序,即在传输字节流前,先传输被作为BOM的字符"零宽无中断空格"。这个字符的编码是FEFF,而反过来的FFFE(UTF-16)和FFFE0000(UTF-32)在Unicode中都是未定义的码位,不应该出现在实际传输中,所以又删除符号操作。 

Java代码   收藏代码
  1. //将字符转为unicode  
  2.     public static String encode(String str) {  
  3.         if (null == str || str.equals(""))  
  4.             return "输入字符";  
  5.         StringBuffer sb = new StringBuffer();  
  6.         try {  
  7.                         //用16bit数字编码表示一个字符,每8bit用byte表示。  
  8.             byte bytesUtf16[] = str.getBytes("UTF-16");  
  9.             for (int n = 0; n < bytesUtf16.length; n++) {  
  10.                 // 截取后面8位,并用16进制表示。  
  11.                 str = (java.lang.Integer.toHexString(bytesUtf16[n] & 0XFF));  
  12.                 // 将获得的16进制表示连成串  
  13.                 sb.append((str.length() == 1) ? ("0" + str) : str);  
  14.             }  
  15.             // 去除第一个标记字符  
  16.             str = sb.toString().toUpperCase().substring(4);  
  17.             char[] chs = str.toCharArray();  
  18.             str = "";  
  19.             for (int i = 0; i < chs.length; i = i + 4) {  
  20.                 str += "\\u" + chs[i] + chs[i+1] + chs[i+2] + chs[i+3];  
  21.             }  
  22.         } catch (Exception e) {  
  23.             System.out.print(e.getMessage());  
  24.             str = "程序出现异常";  
  25.         } finally {  
  26.             return str;  
  27.         }  
  28.     }  
  29.       
  30.     //將unicode转为字符  
  31.     public static String decode(final String str) {  
  32.         if(null == str || str.equals("")){  
  33.             return "輸入unicode";  
  34.         }  
  35.                  //用正则表达式验证  
  36.         Pattern p = Pattern.compile("(\\\\u[0-9a-fA-F]{4})+");  
  37.         Matcher m = p.matcher(str);  
  38.         if(!(m.find() && m.group().equals(str))){  
  39.             return "非法格式";  
  40.         }  
  41.         String[] strs = str.split("u");  
  42.         StringBuffer sb = new StringBuffer();  
  43.         for (int i = 1; i <= strs.length - 1; i++) {  
  44.             sb.append(new Character((char) Integer.parseInt(strs[i].replace("\\", ""), 16)));  
  45.         }  
  46.         return sb.toString();  
  47.     }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值