乱码可恢复,因其本质是UTF-8字节被ISO-8859-1错误解码为Unicode码点与原字节值一一对应的伪字符串,再用ISO-8859-1编码还原字节、UTF-8解码即可复原。

乱码不是“坏了”,而是字节被错解了。只要原始字节没丢、没截断,用 ISO-8859-1 误解 UTF-8 后的字符串,通常能原样恢复——关键在于理解这个过程怎么发生的,以及该在什么环节操作。
乱码是怎么产生的
当一段真实的 UTF-8 字节(比如“中”的编码是 0xE4 0xB8 0xAD)被错误地用 ISO-8859-1 解码时:
- 每个 UTF-8 字节都被当作一个独立的 Latin-1 字符处理;
-
0xE4→ UnicodeU+00E4(字符 ä),0xB8→U+00B8(¸),0xAD→U+00AD(); - 结果字符串看起来像乱码(如 “且),但它内部的 Unicode 码点值,恰好等于原始 UTF-8 的每个字节值。
为什么能恢复:ISO-8859-1 的字节透明性
ISO-8859-1 编码规则极其简单:Unicode 码点 0x00–0xFF 直接映射为同值字节。也就是说:
- 字符
ä(U+00E4)用 ISO-8859-1 编码 → 字节0xE4; - 字符
¸(U+00B8)→0xB8; - 所以
wrongStr.getBytes("ISO-8859-1")得到的字节数组,和原始 UTF-8 字节完全一致。
标准恢复写法(仅适用于 ISO-8859-1 误解 UTF-8 场景)
假设你已有乱码字符串 wrongStr(它其实是被 ISO-8859-1 错解后的结果):
立即学习“Java免费学习笔记(深入)”;
String restored = new String(wrongStr.getBytes("ISO-8859-1"), "UTF-8");
这行代码分两步:
-
wrongStr.getBytes("ISO-8859-1"):把每个字符按 Latin-1 规则“压回”字节,还原出原始 UTF-8 字节流; -
new String(..., "UTF-8"):用 UTF-8 正确解码这些字节,得到原始中文或符号。
哪些情况不能这么恢复
这个技巧只在特定条件下有效,不是万能解药:
- 原始数据必须是合法 UTF-8 字节(常见场景基本满足);
- 中间不能经过任何修改(如 substring、replace、trim 操作可能破坏字节对应关系);
- 不能用其他编码再 encode 过(比如用了
GBK或UTF-16再 getBytes,字节就变了); - 如果乱码来自 GBK/GB2312 误解,或字节流本身已损坏(如网络丢包、文件截断),此方法无效。


















