Java截取含中文字符串防乱码的核心是按字节边界安全截断而非用substring硬切:需显式指定UTF-8编码获取字节数组,累计字节数时识别多字节字符长度,确保不截断半个汉字,并全链路统一UTF-8编码。

Java 中截取含中文的字符串防止乱码,核心是**不按字符数(substring)硬切,而要按字节边界安全截断**。因为中文在 UTF-8 中占 3 字节、GBK 中占 2 字节,直接用 substring(0, n) 可能切在某个汉字中间,导致后续解码失败、显示为 或其他乱码符号。
明确指定编码再操作字节数组
Java 的 String.getBytes() 默认使用平台编码(如 Windows 是 GBK),不可靠。必须显式传入编码名(推荐 UTF-8):
- 先用
str.getBytes("UTF-8")得到真实字节序列 - 按需截取前
n字节(注意不能超长) - 再用
new String(bytes, "UTF-8")重建字符串
这样可确保字节和编码严格对应,避免默认编码不一致引发的隐性乱码。
避免截断多字节字符(关键防护)
即使指定了 UTF-8,若截取位置落在某个中文字符的中间字节上(比如只取了 3 字节中的前 2 字节),解码仍会失败。安全做法是:从前往后累计字节数,遇到非 ASCII 字符(c > 0x7F)时,按其实际 UTF-8 编码长度(2/3/4 字节)累加,一旦超过目标字节数,就停在上一个完整字符处。
立即学习“Java免费学习笔记(深入)”;
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 例如:
"我ABC"截 4 字节 → “我”占 3 字节,“A”占 1 字节 → 刚好 4 字节 → 结果是"我A" - 若截 5 字节 → “我A”共 4 字节,“B”再加 1 字节 → 共 5 字节 → 结果是
"我AB" - 绝不会出现“我AB”或半个“汉”字
统一项目编码,减少隐患源头
乱码常是“编码链断裂”所致,不只是截取环节的问题:
- 源字符串本身是否以 UTF-8 正确构造?如读文件时用了
InputStreamReader(file, "UTF-8") - 数据库连接 URL 是否带
useUnicode=true&characterEncoding=UTF-8? - Web 层是否配置了 UTF-8 过滤器(
request.setCharacterEncoding("UTF-8"))? - IDE 和文件保存编码是否设为 UTF-8(无 BOM)?
全链路统一 UTF-8,才能让截取逻辑稳定可靠。
用现成工具类或框架辅助
不必每次都手写边界校验。可复用成熟方案:
- Apache Commons Lang 的
StringUtils.abbreviate()(配合宽度感知) - Spring 的
org.springframework.util.StringUtils.truncateUtf8Bytes()(Spring Framework 5.3+) - 自封装工具方法,内部做 UTF-8 字节扫描 + 安全回退(推荐)
这类方法已处理好变长编码边界、空值、负长度等边界情况,比裸用 getBytes 更健壮。

















