用 fs.readFileSync 读一个老系统导出的 csv,console 打出来全是乱码,八成文件是 GBK 编码,而 Node 的字符串默认按 utf8 处理,硬转就是花屏。别急着怪 Excel,先用文本编辑器打开看一眼,乱不乱一眼便知。这种场景装个 iconv-lite 就解决。
读取和写出
const iconv = require('iconv-lite'); const fs = require('fs'); const buf = fs.readFileSync('a.csv'); const str = iconv.decode(buf, 'gbk'); fs.writeFileSync('b.csv', iconv.encode(str, 'gbk'));decode 把二进制 Buffer 按指定编码转成字符串,encode 反过来。第三方接口返回的 Buffer 也能这么接,拿到 str 之后再切分、入库都正常,转码只发生在输入输出边界,字符串层面不再有编码问题。编码名拼写错了会直接抛异常,不是静默失败,报错反而好排查。
编码名怎么选
国内常见的是 gbk 和 gb18030。gbk 覆盖常用汉字,遇到生僻字、人名里的罕见字可能转不出来,用 gb18030 更保险,它是 gbk 的超集。转出来出现问号或方框,多半是编码名选小了,先换 gb18030 再说,big5 繁体文件同理,包里也支持。
两个常见场景
- 导出的 csv 要用 Excel 双击打开不乱码:utf8 加 BOM,或者干脆存 gbk,二选一。
- 对接老网站接口:响应头没写编码,先按字节收下来,试 gbk 解码,还不对再换 gb18030。
- 读 Windows 记事本导出的老文件:多数是 ANSI 也就是 gbk,按上面的写法直接转。
这个包是纯 js 实现,浏览器里也能用,前后端行为一致,不用各调各的。文件不大一次读完全转就行,大文件用流式读写,内存才稳。iconv-lite 一个包覆盖常见编码,转码前记得留一份原始文件,转错了还有退路。