用 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 一个包覆盖常见编码,转码前记得留一份原始文件,转错了还有退路。