【131】Java把\u开头的Unicode编码转换成汉字

最近工作中遇到需要调用第三方接口的需求。第三方接口返回的字符串中,会把中文转义成 \u + Unicode 的形式。因此,我需要再把 \u + Unicode 转换成汉字。

这里,我们需要认识到 Java 代码对于 \u 字符处理的内外有别。如果是编写程序的时候,直接在字符串变量里面写 \u + Unicode ,Java 会自动转成汉字。但是 Java 程序对于从外部输入的 \u + Unicode 字符,会把 \u 视作普通字符,相当于 Java 字符串中的 "\\u"

下面是工具类代码,用于把 \u + Unicode 转换成汉字。

package zhangchao.common.unicode;

import java.util.regex.Pattern;

/**
 * 字符串中存在 反斜杠+u 开头 的Unicode字符。本类用于把那些Unicode字符串转换成汉字
 * @author 张超
 *
 */
public final class UicodeBackslashU {
	// 单个字符的正则表达式
	private static final String singlePattern = "[0-9|a-f|A-F]";
	// 4个字符的正则表达式
	private static final String pattern = singlePattern + singlePattern +
			singlePattern + singlePattern;
	

	
	/**
	 * 把 \\u 开头的单字转成汉字,如 \\u6B65 -> 步
	 * @param str
	 * @return
	 */
	private static String ustartToCn(final String str) {
		StringBuilder sb = new StringBuilder().append("0x")
				.append(str.substring(2, 6));
		Integer codeInteger = Integer.decode(sb.toString());
		int code = codeInteger.intValue();
		char c = (char)code;
		return String.valueOf(c);
	}
	
	/**
	 * 字符串是否以Unicode字符开头。约定Unicode字符以 \\u开头。
	 * @param str 字符串
	 * @return true表示以Unicode字符开头.
	 */
	private static boolean isStartWithUnicode(final String str) {
		if (null == str || str.length() == 0) {
			return false;
		}
		if (!str.startsWith("\\u")) {
			return false;
		}
		// \u6B65
		if (str.length() < 6) {
			return false;
		}
		String content = str.substring(2, 6);
		
		boolean isMatch = Pattern.matches(pattern, content);
		return isMatch;
	}
	
	/**
	 * 字符串中,所有以 \\u 开头的UNICODE字符串,全部替换成汉字
	 * @param strParam
	 * @return
	 */
	public static String unicodeToCn(final String str) {
		// 用于构建新的字符串
		StringBuilder sb = new StringBuilder();
		// 从左向右扫描字符串。tmpStr是还没有被扫描的剩余字符串。
		// 下面有两个判断分支:
		// 1. 如果剩余字符串是Unicode字符开头,就把Unicode转换成汉字,加到StringBuilder中。然后跳过这个Unicode字符。
		// 2.反之, 如果剩余字符串不是Unicode字符开头,把普通字符加入StringBuilder,向右跳过1.
		int length = str.length();
		for (int i = 0; i < length;) {
			String tmpStr = str.substring(i);
			if (isStartWithUnicode(tmpStr)) { // 分支1
				sb.append(ustartToCn(tmpStr));
				i += 6;
			} else { // 分支2
				sb.append(str.substring(i, i + 1));
				i++;
			}
		}
		return sb.toString();
	}
}

下面我们要测试一下代码。我们读取了一个JSON文件,文件中有 \u + Unicode 的内容。

读取文件的 FileUtils.java:

package zhangchao.common.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * 文件工具类
 * @author 张超
 *
 */
public final class FileUtils {
	
	/**
	 * 读取文件内容,并把内容作为字符串返回
	 * @param f 要读取的文件
	 * @return 字符串形式的文件内容。
	 */
	public static String readAsString(File f) {
		BufferedReader br = null;
		StringBuilder sb = new StringBuilder();
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
			String str = br.readLine();
			while (null != str) {
				sb.append(str).append("\n");
				str = br.readLine();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (null != br) {
				br.close();
				br = null;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return sb.toString();
	}
}

用于测试的主类,TestUnicode.java:

package zhangchao.test;

import zhangchao.common.utils.FileUtils;
import zhangchao.common.unicode.UicodeBackslashU;

import java.io.File;

/**
 * 测试 \\u + Unicode 转换成汉字
 * @author 张超
 *
 */
public class TestUnicode {

	public static void main(String[] args) {
		String jsonStr = FileUtils.readAsString(new File("src/test/resources/MyJson.json"));
		String str = UicodeBackslashU.unicodeToCn(jsonStr);
		System.out.println(str);
	}

}

MyJson.json 的文件内容:

{
    "msg":"success",
    "data":{
        "userId":"12363324",
        "collegeName":"\u8BA1\u7B97\u673A\u5B66\u9662",
        "className":"\u8F6F\u4EF6\u4E00\u73ED"
    }
}

程序的运行结果:

{
    "msg":"success",
    "data":{
        "userId":"12363324",
        "collegeName":"计算机学院",
        "className":"软件一班"
    }
}

下面的图片解释了 UicodeBackslashU 类的工作原理:
1.png

在这里插入图片描述

  • 15
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值