在 Java 里处理 Unicode(统一码),核心要理解 Java 内部全部使用 UTF-16 表示字符,以及 源码 / 文件 / 网络 / 数据库 的编码问题。下面从常见场景系统说明。
char 和 String 都是 UTF-16char:16 位,表示一个 UTF-16 代码单元String:底层是 char[]U+0000 ~ U+10FFFF⚠️ 注意:
U+0000 ~ U+FFFF → 一个 charU+10000 以上 → 两个 char(代理对)char c = '中';
int codePoint = c; // 20013
System.out.println(codePoint);
// Unicode 转字符
char ch = (char) 20013;
System.out.println(ch); // 中
String s = "\u4e2d\u6587"; // 中文
System.out.println(s);
✅ Java 编译器会在编译阶段把 \uXXXX 转成对应字符。
❌ 错误方式(会拆散 Emoji):
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
}
✅ 正确方式:
for (int i = 0; i < s.length(); ) {
int codePoint = s.codePointAt(i);
System.out.println(Integer.toHexString(codePoint));
i += Character.charCount(codePoint);
}
或使用 API:
s.codePoints().forEach(cp ->
System.out.println(Integer.toHexString(cp))
);
这是 最容易出现乱码的地方。
byte[] bytes = "中文".getBytes(StandardCharsets.UTF_8);
String s = new String(bytes, StandardCharsets.UTF_8);
❌ 不推荐:
"中文".getBytes(); // 依赖平台默认编码
✅ 始终显式指定 UTF-8
Files.writeString(
Paths.get("a.txt"),
"中文",
StandardCharsets.UTF_8
);
String s = Files.readString(
Paths.get("a.txt"),
StandardCharsets.UTF_8
);
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
utf8mb4)jdbc:mysql://localhost/db?useUnicode=true&characterEncoding=UTF-8
| 问题 | 原因 | 解决 |
|---|---|---|
| Emoji 被截断 | 用 charAt | 用 codePoint |
| 乱码 | byte ↔ String 编码不一致 | 统一 UTF-8 |
| 文件乱码 | Reader/Writer 未指定编码 | 指定 UTF-8 |
| 数据库乱码 | 非 UTF-8 | utf8mb4 |
boolean isSupplementary(int cp) {
return cp > 0xFFFF;
}
\u 形式String toUnicode(int cp) {
return String.format("\\u%04X", cp);
}
✅ Java 内部永远用 UTF-16,对外永远用 UTF-8,处理字符串时优先使用 codePoint,而不是 char。
如果你有具体场景(文件、网络、正则、Emoji、序列化、JSON、数据库),可以告诉我,我可以给更针对性的示例。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。