[转]Java的Unicode编码转化(多种情况处理方法)

转:

[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;
}

你可能感兴趣的:(java)