我一直觉得“编码”这个词被严重低估了。打工人天天对着屏幕,知道文件乱码了要改 UTF-8,知道网页里 Base64 是某种字符串,知道 AI 编程要写清楚上下文,但真要问一句“编码到底是什么”,很多人反而说不清楚。我最早也是从“中文变问号”开始意识到这东西不简单,后来接触越多越发现,编码不只是字符集,它横跨压缩算法、通信协议、业务规范、AI 上下文,甚至安全攻防,全都是“同一件事”的不同面孔。
这篇文章不打算写成教科书,我想顺着几个真实场景,把这十个方向里最常被搜索、最容易踩坑的“编码问题”串起来讲清楚:乱码怎么查、哈夫曼和 LZW 在干嘛、曼彻斯特和 USB 有什么关系、位置编码为什么在 AI 里绕不开、业务编码怎么定规则、路径编码绕过又是怎么回事。不管你是写 Java 的、调 AI 接口的、做嵌入式的,还是刚入行被这些词砸晕的新人,看完应该都能对“编码”建立起一个立体的认识。
1. 字符编码:乱码的根子在于“规则不一致”
1.1 ASCII 之后,字符集开始分家
聊编码之前,先把最基础也最烦人的一块捋清楚:字符编码。你会发现所有乱码问题,最后都能归结为一句大白话——写入文件用的规则,和读取文件用的规则,对不上。
最早计算机用的是 ASCII,7 个 bit,总共 128 个字符,英文、数字、标点够了。但中文、日文、韩文这些非拉丁文字没法塞进去,于是各地区各搞各的。简体中文这边,GB2312、GBK、GB18030 一路演进,GB18030 甚至能用四个字节表示全部 Unicode 字符,兼容性比 GBK 更好。但本质都是“用自己的映射表把字符变成字节”。
Unicode 的出现是想终结这种混乱,它给每个字符一个唯一的编号(码点),比如“编”的 Unicode 码点是 U+7F16。但 Unicode 只是编号,怎么存还得看编码方案,最常用的就是 UTF-8。UTF-8 是变长编码,英文 1 字节,中文通常 3 字节,每个字节开头有标志位,解起来不会歧义。
我之前帮人排查过一个 Java 项目的乱码:代码文件是 UTF-8 保存的,但 Maven 编译时没指定编码,Windows 默认用 GBK 去读源文件,结果所有中文字符串编译后全变成“锟斤拷”。这就是典型的“写入是 UTF-8,读取是 GBK”。后来在 pom.xml 里统一加 project.build.sourceEncoding 为 UTF-8,问题才根除。所以治理乱码的关键是:进出口的字符编码必须锁死在同一种,最常见也最通用的就是 UTF-8。
1.2 一个乱码问题的完整排查思路
这里我把日常最容易碰到乱码的几个场景整理一下,都是搜到烂的问题,但真上手时很多人还是会漏掉一两个环节。
第一类是 IDE 或终端显示乱码。VS Code 的终端、日志输出、YAML 配置文件里出现中文乱码,很多情况下不是代码问题,而是文件读进来的编码和编辑器默认打开方式不一致。VS Code 右下角会显示当前文件编码,如果显示 GBK 而你期望 UTF-8,点它选择“通过编码重新打开”即可。想一劳永逸,把 files.encoding 默认改成 utf8,再给 files.autoGuessEncoding 打开,让它自动猜编码。
第二类是前后端交互乱码。常见于 AJAX 请求,前端页面是 UTF-8,后端却按 ISO-8859-1 解析。我见过最典型的场景是 Java 的 request.setCharacterEncoding("UTF-8") 没写,或者写在了读取参数之后。正确做法是:在 Servlet 里读取任何参数之前先设置编码;如果是 Spring Boot,直接在配置里统一 server.servlet.encoding.force=true。前端也要注意,fetch 或 axios 默认发的是 UTF-8,真正容易乱的是响应头没带 charset=utf-8。
第三类是文件传输乱码。Xftp 从 Windows 传文件到 Linux,如果 Windows 那边文件名是 GBK,传到 UTF-8 环境的 Linux 上就全是菱形问号。这不是文件内容坏了,是文件名编码变了。Xftp 有个“传输文件名编码”的设置,UTF-8 和 GBK 之间得手动切一下。终端里也可以用 convmv 批量转换文件名,比如 convmv -f GBK -t UTF-8 --notest *.txt。手机上的 txt 文件也一样,很多老阅读器只认 GBK,手机上存的是 UTF-8,直接用记事本另存或者用 iconv 转一下就行。
还有一个容易被人忽略的场景:Python 连接 Oracle 时用 GBK 读中文,报 UnicodeDecodeError。此时不是 Python 文件本身的问题,而是数据库客户端字符集没配对。python-oracledb 可以在连接参数里指定 encoding="UTF-8"、nencoding="UTF-8",同时在 Oracle 端确认 NLS_LANG 一致,两边都对齐后代码基本不用改。
一句话总结:遇到乱码,先确认四个点——文件保存编码、程序读取编码、传输通道编码、显示终端编码,永远让它们保持一致。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 压缩编码:用更短的信息表达同样多的内容
2.1 哈夫曼编码:给高频字符走更短的路
从字符编码往上走
