杰瑞科技汇

Java中如何将中文转换为Unicode?

Java 字符串的内部表示

一个非常重要的概念是:Java 字符串(String)在内部就是使用 UTF-16 编码存储的,这意味着,一个 char 变量通常可以表示一个 Unicode 字符(码点)。

  • 对于大多数常见的字符(包括中文),码点范围在 \u0000\uffff 之间,可以用一个 char 表示。
  • 但对于一些不常用的字符(如某些生僻字、表情符号),码点范围在 \uffff0x10ffff 之间,需要用两个 char(一个“代理对”,surrogate pair)来表示。

我们通常说的“转 Unicode”,就是遍历字符串中的每一个字符码点,并将其格式化为 \uxxxx 的形式。


最推荐的方法(处理所有字符,包括生僻字)

这种方法使用 codePointAt() 来获取每个字符的完整码点,然后使用 Integer.toHexString() 进行格式化,它能正确处理所有 Unicode 字符,包括需要代理对的生僻字。

代码实现

public class ChineseToUnicode {
    /**
     * 将字符串转换为 Unicode 码点表示形式 ( \u4e2d\u6587)
     * @param str 要转换的字符串
     * @return 转换后的 Unicode 字符串
     */
    public static String stringToUnicode(String str) {
        if (str == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        // 遍历字符串中的每一个码点
        for (int i = 0; i < str.length(); i++) {
            int codePoint = str.codePointAt(i);
            // 处理代理对(即需要两个 char 表示的字符)
            if (Character.isSupplementaryCodePoint(codePoint)) {
                i++; // 跳过下一个 char
            }
            sb.append(String.format("\\u%04x", codePoint));
        }
        return sb.toString();
    }
    public static void main(String[] args) {
        String chineseStr = "中文测试";
        String unicodeStr = stringToUnicode(chineseStr);
        System.out.println("原始字符串: " + chineseStr);
        System.out.println("Unicode 字符串: " + unicodeStr);
        // 包含生僻字的例子
        String rareCharStr = "𠮷𠮷"; // 这两个字是生僻字,需要代理对表示
        String rareUnicodeStr = stringToUnicode(rareCharStr);
        System.out.println("\n原始字符串 (生僻字): " + rareCharStr);
        System.out.println("Unicode 字符串 (生僻字): " + rareUnicodeStr);
    }
}

代码解释

  1. StringBuilder sb: 用于高效地拼接字符串,避免在循环中频繁创建 String 对象。
  2. str.codePointAt(i): 这是核心方法,它返回从指定索引 i 开始的字符的 Unicode 码点,对于普通字符,它返回一个 char 的值;对于需要代理对的字符,它返回完整的码点(一个 int 类型)。
  3. Character.isSupplementaryCodePoint(codePoint): 判断这个码点是否是一个“补充字符”,即是否需要两个 char 来表示。
  4. if (Character.isSupplementaryCodePoint(codePoint)) { i++; }: 如果是补充字符,我们需要将索引 i 加一,跳过组成这个字符的第二个 char,这确保了我们能正确地遍历整个字符串。
  5. String.format("\\u%04x", codePoint): 这是格式化字符串的关键。
    • \\u: 一个反斜杠加 u,这是 Unicode 转义序列的前缀,因为 \ 是转义字符,所以需要写成 \\ 来表示一个字面的反斜杠。
    • %04x: 这是一个格式说明符。
      • %x: 表示将整数格式化为十六进制小写字母。
      • 04: 表示至少占 4 位,如果不足 4 位,则在前面补零,这对于保证 \u 后面总是有 4 位十六进制数非常重要( 的码点是 4e2d,而不是 4e2d4e2d)。

输出结果

原始字符串: 中文测试
Unicode 字符串: \u4e2d\u6587\u6d4b\u8bd5
原始字符串 (生僻字): 𠮷𠮷
Unicode 字符串 (生僻字): \u20a3b\u20a3b

(注意: 的实际码点是 0x20A3B)


简单方法(仅适用于 BMP 字符)

如果你的字符串中只包含基本多语言平面的字符(即所有常见的中文、英文、日文、韩文等,但不包含生僻字、表情符号等),可以使用更简单的方法,这种方法直接遍历 char 数组。

代码实现

public class SimpleChineseToUnicode {
    /**
     * 将字符串转换为 Unicode 码点表示形式 (简单版)
     * 注意:此方法不适用于需要代理对的字符(如生僻字、表情符号)。
     * @param str 要转换的字符串
     * @return 转换后的 Unicode 字符串
     */
    public static String stringToUnicodeSimple(String str) {
        if (str == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (char c : str.toCharArray()) {
            sb.append(String.format("\\u%04x", (int) c));
        }
        return sb.toString();
    }
    public static void main(String[] args) {
        String chineseStr = "中文测试";
        String unicodeStr = stringToUnicodeSimple(chineseStr);
        System.out.println("原始字符串: " + chineseStr);
        System.out.println("Unicode 字符串: " + unicodeStr);
        // 这个方法会错误地处理生僻字
        String rareCharStr = "𠮷";
        String rareUnicodeStr = stringToUnicodeSimple(rareCharStr);
        System.out.println("\n原始字符串 (生僻字): " + rareCharStr);
        System.out.println("Unicode 字符串 (生僻字, 错误): " + rareUnicodeStr);
    }
}

代码解释

  • str.toCharArray(): 将 String 转换为一个 char 数组。
  • for (char c : ...): 遍历每一个 char
  • (int) c: 将 char 强制转换为 int,得到它的码点值。

输出结果

原始字符串: 中文测试
Unicode 字符串: \u4e2d\u6587\u6d4b\u8bd5
原始字符串 (生僻字): 𠮷
Unicode 字符串 (生僻字, 错误): \ud842\udf3b

注意,对于生僻字 ,这个方法输出了它的代理对 0xd8420xdf3b,而不是完整的码点 0x20a3b不推荐在生产环境中使用这种方法,除非你 100% 确定你的字符串不包含任何 BMP 之外的字符。


总结与对比

特性 方法一 (推荐) 方法二 (简单)
核心方法 codePointAt() toCharArray()
处理范围 所有 Unicode 字符 (包括生僻字、表情符号) BMP 字符 (常见字符)
正确性 高,能正确处理代理对 低,会错误拆分代理对
代码复杂度 稍高,需要处理代理对逻辑 非常简单
适用场景 通用场景,任何可能包含特殊字符的字符串 已知字符串内容仅限于 BMP 字符的特定场景

在进行任何“字符串转 Unicode”的操作时,请优先选择方法一,它更健壮、更通用,能够处理所有可能的字符,避免因生僻字或特殊符号导致的潜在问题,方法二虽然简单,但存在缺陷,仅适用于非常受限的环境。

分享:
扫描分享到社交APP
上一篇
下一篇