unicode字符串解析
- 2019 年 10 月 30 日
- 筆記
现象和答案
在http接口接收时,很多接口提供方都喜欢把汉字通过unicode的方式传过来,而数字和字母保持不变,就像这样。
{“Content”:"[reply]CocoWu892[/reply]nu6c9fu901au662fu6700u91cdu8981u7684u6280u80fdu4e4bu4e00"}
这里就必须涉及到一个带unicode字符串转成正常字符串的过程。网上关于这块问题有很多博客,大部分都是一样的,实现思路是在字符串中找到n[0-9]{4}
字符串,并将匹配到的四位数字通过Integer.parseInt()
来转成字符串。我认为一定有开源jar完成了这个工作,我们应该不用自造轮子。经过寻找,发现fastjson能自动的转换unicode字符串。
fastjson,已经实现unicode字符串解析,JSON.parseObject(String)等方法都可以。
实现原理,fastjson实现过程,自造轮子
接下来内容是具体实现,实现方式原理和fastjson的实现方式。
我们先了解一下unicode码,unicode码u8981
中u
是标示,告诉你这是一个unicode码,8981
是码的内容,是16位数字,根据8981
在unicode码库中找到对应字符。在string中的字符实际是
\
,8981
可以通过(char)Integer.parseInt("8981",16)
来转码。
在fastjson中,unicode的解析在JSONLexerBase.scanString()
。fastjson字符串(遍历),发现当前字符是"
时,便执行该方法。scanString()
方法内容如下,遍历之后的字符,如果是“
,跳出循环;如果是\
进入特殊字符解析,比如"
,n
,u
之类,如果是u
便开始unicode解析。
ch = next(); switch (ch) { case ... case 'u': char u1 = ch = next(); char u2 = ch = next(); char u3 = ch = next(); char u4 = ch = next(); int val = Integer.parseInt(new String(new char[] { u1, u2, u3, u4 }), 16); putChar((char) val); break; }
如果仅仅做一个unicode解析,可以使用正则进行匹配和替换,这是自造轮子,仿的String.replaceAll();
public String parseString(String content) { String unicodeRegix = "\\u(.{4})"; Pattern pattern = Pattern.compile(unicodeRegix); Matcher matcher = pattern.matcher(content); StringBuffer sb = new StringBuffer(); while (matcher.find()) { String result = matcher.group(1); int val = Integer.valueOf(result,16); matcher.appendReplacement(sb, "" + (char) val); } matcher.appendTail(sb); return sb.toString(); }
调用和结果
@Test public void parseString() { UnicodeUtil unicodeUtil = new UnicodeUtil(); System.out.println(unicodeUtil.parseString("{"Content":"[reply]CocoWu892[\/reply]\n\u6c9f\u901a\u662f" + "\u6700\u91cd\u8981\u7684\u6280\u80fd\u4e4b\u4e00"}")); }
Connected to the target VM, address: ‘127.0.0.1:60255’, transport: ‘socket’ {“Content”:"[reply]CocoWu892[/reply]n沟通是最重要的技能之一"}