[转]Java的Unicode编码转化(多种情况处理方法)
- - PHP & Java[JDK自带了native2ascii,但是很多时候还是需要自己写程序去解析unicode编码问题,网上的decodeUnicode
这个方法实现有比较严重的解析问题实在是个大坑,转了作者的这篇文章希望大家不要再用decodeUnicode了,
还有就是使用别人代码之前毋必仔细尝试. ]
原文:http://448230305.iteye.com/blog/2159336.
转:
[JDK自带了native2ascii,但是很多时候还是需要自己写程序去解析unicode编码问题,网上的decodeUnicode 这个方法实现有比较严重的解析问题实在是个大坑,转了作者的这篇文章希望大家不要再用decodeUnicode了, 还有就是使用别人代码之前毋必仔细尝试!] 原文:http://448230305.iteye.com/blog/2159336
Java的Unicode编码转化(多种情况处理方法)
Java转unicode转中文的情况使用的场景很多,是一个很常见的需求,按理来说,这样的功能应该被java集成起来,不过很遗憾,java提供的方法很烂,很多时候我们需要自己去写。
好在这个需求的源代码网上很多,在查资料的过程中,我找到啦好几种,下面我将我找到的资料分享和我自己实现的方法提供给大家;希望大家能有个参考;
1、java中使用的是unicode编码,所以如果我们得到的本身就是一个unicode编码,那么我们可以直接print出来的就是中文:
public static void main(String[] args){ String string= "\u9999\u714e\u9a6c\u9c9b\u9c7c\u7684\u535a\u5ba2"; System.out.println(string); }
输出:
香煎马鲛鱼的博客
可是像上面那种情况在实际问题里是很少见的,在1例子中,”\”是转义字符,实际我们得到的unicode编码是这样的:
public static void main(String[] args){ String string= "\\u9999\\u714e\\u9a6c\\u9c9b\\u9c7c\\u7684\\u535a\\u5ba2"; System.out.println(string); }
而这样得到的输出结果就变成了这样:
\u9999\u714e\u9a6c\u9c9b\u9c7c\u7684\u535a\u5ba2
这样的结果肯定是我们不想要的,那么解决方法是什么呢:
方法一:这是在网上最常见的一种方法,直接将方法decodeUnicode放在类中就可以,方便,不过缺点就是代码量比较大,下面我们测试一下它的转义能力
\u9999\\u714e\u9c7c香\u714e鱼香\煎鱼转义有误
测试项 | 例子 | 输出 | 正确结果 | 总结 |
---|---|---|---|---|
基本能力 | \u9999\u714e\u9c7c | 香煎鱼 | 香煎鱼 | 正确 |
中英文数字混合 | 1\u9999123\u714ehi\u9c7ca | 1香123煎hi鱼a | 1香123煎hi鱼a | 正确 |
中英文,特殊字符混合 | \u9999\u\u714e\u9c7c | (错误) | 香\u煎鱼 | 无法正常运行 |
可见,方法一虽然能对中英混合进行识别,但对\和\u的识别仍然存在问题,我们可以给他打70分;
public static String decodeUnicode(String theString) { char aChar; int len = theString.length(); StringBuffer outBuffer = new StringBuffer(len); for (int x = 0; x < len;) { aChar = theString.charAt(x++); if (aChar == '\\') { aChar = theString.charAt(x++); if (aChar == 'u') { // Read the xxxx int value = 0; for (int i = 0; i < 4; i++) { aChar = theString.charAt(x++); switch (aChar) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': value = (value << 4) + aChar - '0'; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': value = (value << 4) + 10 + aChar - 'a'; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': value = (value << 4) + 10 + aChar - 'A'; break; default: throw new IllegalArgumentException( "Malformed \\uxxxx encoding."); } } outBuffer.append((char) value); } else { if (aChar == 't') aChar = '\t'; else if (aChar == 'r') aChar = '\r'; else if (aChar == 'n') aChar = '\n'; else if (aChar == 'f') aChar = '\f'; outBuffer.append(aChar); } } else outBuffer.append(aChar); } return outBuffer.toString(); } }
方法二:此种方法在网上也比较常见,代码量少,可读性强是它最大的优点,但是,它的转义能力……大家自己体会一下吧;
测试项 | 例子 | 输出 | 正确结果 | 总结 |
---|---|---|---|---|
基本能力 | \u9999\u714e\u9c7c | 香煎鱼 | 香煎鱼 | 正确 |
中英文数字混合 | 1\u9999123\u714ehi\u9c7ca | (错误) | 1香123煎hi鱼a | 无法正常运行 |
中英文,特殊字符混合 | \u9999\u\u714e\u9c7c | (错误) | 香\u煎鱼 | 无法正常运行 |
\u9999\\u714e\u9c7c | (错误) | 香\u煎鱼 | 无法正常运行 |
它的转义能力决定它的实用性不强,但是鉴于它比较简单,所以还是有一定市场的,不过也请大家谨慎使用,根据我的测试,这种转码方式只对全中文有效
public static String ascii2native_orl(String ascii) { int n = ascii.length() / 6; StringBuilder sb = new StringBuilder(n); for (int i = 0, j = 2; i < n; i++, j += 6) { String code = ascii.substring(j, j + 4); char ch = (char) Integer.parseInt(code, 16); sb.append(ch); } return sb.toString(); }
方法三:既然方法二有问题,那么我们能不能对他进行一些改进,让它适应性更强呢,当然,如果方法二加上正则表达式,就有更强的功能了
测试项 | 例子 | 输出 | 正确结果 | 总结 |
---|---|---|---|---|
基本能力 | \u9999\u714e\u9c7c | 香煎鱼 | 香煎鱼 | 正确 |
中英文数字混合 | 1\u9999123\u714ehi\u9c7ca | 1香123煎hi鱼a | 1香123煎hi鱼a | 正确 |
中英文,特殊字符混合 | \u9999\u\u714e\u9c7c | 香\u煎鱼 | 香\u煎鱼 | 正确 |
\u9999\\u714e\u9c7c | 香\煎鱼 | 香\u煎鱼 | 正确 |
这种方法很好利用了正则表达式,代码可读性强,转义能力也很不错,强烈推荐
public static String ascii2native(String ascii) { List<String> ascii_s = new ArrayList<String>(); String zhengz = "\\\\u[0-9,a-f,A-F]{4}"; Pattern p = Pattern.compile(zhengz); Matcher m = p.matcher(ascii); while (m.find()) { ascii_s.add(m.group()); } for (int i = 0, j = 2; i < ascii_s.size(); i++) { String code = ascii_s.get(i).substring(j, j + 4); char ch = (char) Integer.parseInt(code, 16); ascii = ascii.replace(ascii_s.get(i), String.valueOf(ch)); } return ascii; }