1. 概述
在Java中处理字符串(String
)时,我们经常需要将其编码为特定的字符集(charset)。
本文将通过实际示例,介绍如何将字符串编码为 UTF-8 的几种常用方式。
如果你对字符编码底层机制感兴趣,可以参考我们的《Java字符编码指南》。
✅ 提醒:本文重点是“编码为UTF-8”,不是“判断是否为UTF-8”或“检测乱码”。
2. 问题背景
我们先通过一个实际例子,理解为什么需要显式编码为 UTF-8。
考虑这句德语字符串:
String germanString = "Entwickeln Sie mit Vergnügen";
byte[] germanBytes = germanString.getBytes();
String asciiEncodedString = new String(germanBytes, StandardCharsets.US_ASCII);
assertNotEquals(asciiEncodedString, germanString);
执行后,asciiEncodedString
输出为 "Entwickeln Sie mit Vergn?gen"
—— 原因是 ü
不是 ASCII 字符,在 US-ASCII 编码下会被替换为 ?
,导致信息丢失。
⚠️ 这就是典型的“乱码踩坑”:看似只是转个字节流,结果非英文字符全变成问号。
但如果是纯英文字符串,ASCII 和 UTF-8 是兼容的:
String englishString = "Develop with pleasure";
byte[] englishBytes = englishString.getBytes();
String asciiEncondedEnglishString = new String(englishBytes, StandardCharsets.US_ASCII);
assertEquals(asciiEncondedEnglishString, englishString);
✅ 因为 UTF-8 是 ASCII 的超集,所有 ASCII 字符在 UTF-8 中编码一致。
所以,要安全处理多语言文本,统一使用 UTF-8 是最佳实践。
3. 使用 Java 核心类库编码
Java 中的 String
是不可变的,且内部以 UTF-16 存储,无法直接修改其编码格式。
我们能做的,是将其转换为指定编码的字节数组,再用该字节数组重建字符串。
步骤:
- 调用
String.getBytes(Charset)
获取 UTF-8 字节 - 使用
new String(byte[], Charset)
重建字符串
String rawString = "Entwickeln Sie mit Vergnügen";
byte[] bytes = rawString.getBytes(StandardCharsets.UTF_8);
String utf8EncodedString = new String(bytes, StandardCharsets.UTF_8);
assertEquals(rawString, utf8EncodedString);
✅ 简单粗暴,无需额外依赖,推荐日常使用。
⚠️ 注意:不要使用无参 getBytes()
,它使用平台默认编码(如 Windows 是 Cp1252),极易引发跨平台乱码问题。
4. 使用 Java 7+ 的 StandardCharsets
从 Java 7 开始,java.nio.charset.StandardCharsets
提供了标准字符集常量,比硬编码字符串更安全。
我们可以借助 Charset.encode()
和 Charset.decode()
来完成编码转换:
String rawString = "Entwickeln Sie mit Vergnügen";
ByteBuffer buffer = StandardCharsets.UTF_8.encode(rawString);
String utf8EncodedString = StandardCharsets.UTF_8.decode(buffer).toString();
assertEquals(rawString, utf8EncodedString);
优势:
- ✅ 类型安全,避免拼写错误(如
"UTF8"
vs"UTF-8"
) - ✅ 无需捕获异常,
StandardCharsets
的常量不会为null
- ✅ 适用于 NIO 场景,与
ByteBuffer
集成良好
⚠️ 注意:encode()
返回的是 ByteBuffer
,操作后 position 会改变,如需重复使用记得 rewind()
。
5. 使用 Apache Commons Codec
如果你的项目已经引入了 Apache Commons Codec,可以用它提供的工具类简化操作。
5.1 添加 Maven 依赖
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.14</version>
</dependency>
5.2 使用 StringUtils 工具类
StringUtils
提供了开箱即用的 UTF-8 编解码方法:
String rawString = "Entwickeln Sie mit Vergnügen";
byte[] bytes = StringUtils.getBytesUtf8(rawString);
String utf8EncodedString = StringUtils.newStringUtf8(bytes);
assertEquals(rawString, utf8EncodedString);
优点:
- ✅ 方法命名清晰,
getBytesUtf8
/newStringUtf8
一看就懂 - ✅ 空值安全(传入
null
不会抛异常) - ✅ 代码更简洁,适合频繁编解码场景
❌ 缺点:引入额外依赖,纯 JDK 项目可不考虑。
6. 总结
方法 | 是否需要依赖 | 推荐场景 |
---|---|---|
String.getBytes(StandardCharsets.UTF_8) |
❌ 不需要 | ✅ 日常开发首选 |
StandardCharsets.UTF_8.encode() |
❌ 不需要 | ✅ NIO 场景或需精确控制 ByteBuffer |
StringUtils.getBytesUtf8() |
✅ 需要 commons-codec | ✅ 已使用 Commons 的项目 |
🔚 最终建议:**优先使用
StandardCharsets.UTF_8
+getBytes()
**,简单、安全、无依赖。
所有示例代码已上传至 GitHub:https://github.com/baeldung/tutorials/tree/master/core-java-modules/core-java-string-operations-2