String.getBytes()乱码的根本原因是默认使用平台编码导致编码不一致,必须显式指定StandardCharsets.UTF_8等标准字符集,并在new String时配对使用相同编码。

为什么 String.getBytes() 会乱码
根本原因不是方法本身有问题,而是它默认用平台编码(比如 Windows 上是 GBK,Linux/macOS 上常是 UTF-8),而你的字符串原始编码、目标系统预期编码、文件/网络传输约定编码三者不一致时,字节就“对不上号”。
- 常见错误现象:
new String(bytes)还原后出现 或中文变问号,或前后端联调时 JSON 字段值错乱 - 典型场景:读取本地 UTF-8 编码的配置文件,在 Windows 开发机上用
str.getBytes()发给 Linux 服务端 - 关键区别:
getBytes()无参版依赖Charset.defaultCharset(),而带Charset参数的版本(如str.getBytes(StandardCharsets.UTF_8))才可控 - 性能影响极小,但兼容性风险极高——同一段代码在不同机器上行为可能完全不同
必须显式指定字符集的三个时机
只要涉及跨环境、跨系统、持久化或网络传输,就不能靠默认。
- 写入文件前:
Files.write(path, str.getBytes(StandardCharsets.UTF_8)) - HTTP 请求体构造(如 POST 表单或 JSON):
entity = new StringEntity(str, ContentType.create("text/plain", "UTF-8")) - 加解密或 Base64 编码前:
Base64.getEncoder().encode(str.getBytes(StandardCharsets.UTF_8))
StandardCharsets 比字符串字面量更安全
用 "UTF-8" 字符串传参看似简单,但拼写错误(如 "UTf-8")、JVM 不支持该名称(极少见但存在)、反射调用时类型擦除等问题都会导致 UnsupportedEncodingException;而 StandardCharsets.UTF_8 是编译期常量,类型安全,且 JDK 7+ 均保证可用。
- 正确写法:
str.getBytes(StandardCharsets.UTF_8) - 错误写法:
str.getBytes("UTF-8")(虽常见,但多一层异常风险) - 注意:
StandardCharsets不包含GBK或GB2312,需用Charset.forName("GBK"),但应尽量避免
还原时也要用同一字符集
很多人只记得编码时指定,却在解码时偷懒用 new String(bytes),结果前功尽弃。
立即学习“Java免费学习笔记(深入)”;
- 必须配对使用:
new String(bytes, StandardCharsets.UTF_8) - 如果 bytes 来自不可信来源(如旧数据库、第三方接口),先确认其实际编码,再选对应
Charset,不要硬套 UTF-8 - 调试技巧:打印
bytes十六进制(Arrays.toString(bytes)),对比已知 UTF-8 编码的“你好”(-28 -67 -96 -27 -91 -67)可快速判断是否真为 UTF-8
getBytes 这一行代码里,而在它上下游的编码假设是否统一。最容易被忽略的是:你认为是 UTF-8 的输入源,很可能根本不是。


















