💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
- pre-notify - Node.js支持的编码 - gb2312 - utf8和隐藏在黑夜中的凶手 - BOM - BOM的真面目 - 干掉BOM! - 让node支持gbk——iconv-lite - string_decoder [TOC] ## pre-notify 本文会不断完善,也欢迎各位大佬一起“打磨” ## Node.js支持的编码 当我们读一个文件的时候,可以指定以什么样的编码来读取 ``` fs.readFile('./test.txt','utf8',function(err,data){ console.log(data); //打印出来的就是编码后的字符串 }) ``` **注意:** - Node.js默认支持的编码有utf8、base64,**不支持**gb系列 - 当**不填**写编码时,默认数据的形式**是buffer** ## gb2312 当我们在桌面创建一个.txt时,默认编码是`gb2312`,而又由于Node.js默认是不支持的,So我们通过`fs`读取到的`buffer`是转换不成我们想要的中文文字的。 ![](https://box.kancloud.cn/88137e5ec8548bb605c72d06b5bdf545_393x159.png) 大多数编辑器打开这些文件时候也会乱码。 ![](https://box.kancloud.cn/d695160b5ff3efc6ba6c5b00c8398d3d_182x65.png) >[warning] **注意:** 即使将txt文件的后缀名更改为`.js`也是一样的。 ## utf8和隐藏在黑夜中的凶手 我们可以将文本另存为`utf8` 这样虽然能让中文正常显示,但我们发现在开始的位置却出现了乱码。 ![](https://box.kancloud.cn/2127c09a1a50b3094fa14beab37f2440_427x152.png) 这是为什么呢? 在我们使用unicode系编码的时,因为unicode编码有很多实现,So它会签个名,表示这个文件的是utf8编码的,归utf8管。这样我们再使用编辑器打开的时候它就不会乱码 ![](https://box.kancloud.cn/281beabf0971550559b35100ff253855_146x65.png) **what?!** 编辑器打开都不乱码了,你娃娃node.js读文件toString还要乱码? 脚多麻的,让我们换一个编辑器,嗯,webstorm ![](https://box.kancloud.cn/3c12999497e3334af178f3e644f31c16_177x63.png) **what?!** 不乱码了?这是为什么!! 嗯。。。不要方!不要方!真相只有一个!! 嘿!我们仔细看,没乱码,但变成了一个点 **\`**。 So这个问题有一个合理的推断,我大webstorm为Node.JS主持了公正! 是vscode私自导致的乱码,这锅不该Node.js小兄弟背而该让vscode背! 嗯。。。虽然webstorm中没有乱码,但平白无故多了个 **\`** ,这也不好吧? ## BOM ### BOM的真面目 So,这个 **\`** 是什么?其实我们上面已经说过,如果是unicode系的编码,都会在开头签个名,So这个 **\`** 就是和这个签名,这个字的16进制形式是长这样的 ``` 0xFEFF ``` 转换成buffer是长这样的 ``` <Buffer ef bb bf> ``` 嗯。。。现在我们知道它到底是个什么鬼了,So干不干掉它不就是我们几行代码的事? ### 干掉BOM! ``` let bf2 = fs.readFileSync(path.join(__dirname,'bom.txt'),'utf8'); let result = stripBOM(bf2); console.log(result.toString()); // console.log(result); function stripBOM(content){ if(Buffer.isBuffer(content)){ if(content[0]===0xEF&&content[1]===0xBB&&content[2]===0xBF){ return content.slice(3); } return content; }else{ //是string if(content.charCodeAt(0)===0xFEFF){ return content.slice(1); } return content; } } ``` ## 让node支持gbk——iconv-lite 嗯,其实很简单,一个包的事 ``` let iconv = require('iconv-lite'); let string = iconv.decode(需要转换的buffer,希望用的编码方式) console.log(string) ``` ## string_decoder 我们通常都是用utf8来编码的,utf8编码一个汉字等于3个字节,但有时候我们不一定能一次性拿到完整的数据,可能先拿2个后拿4个,那么第一次拿的时候我们输出出来就会产生乱码。 So我们需要一个东东来帮我们看着,当拿到的东西是一个汉字时要凑够3个字节才输出,否则就先攒着,这就是`string_decoder`的作用之一。 ``` let buffer = Buffer.from('阿弥陀佛'); let buff1 = buffer.slice(0,5); let buff2 = buffer.slice(5); let {StringDecoder} = require('string_decoder'); let sd = new StringDecoder(); console.log(sd.write(buff1).toString()); console.log(sd.write(buff2).toString()); ``` ## encodeURIComponent 设置一些响应头请求头什么的如果有中文,需要进行编码 否则会报错 ![](https://box.kancloud.cn/45619f67597a41e54e63a8cf83b52f0c_600x207.png) ![](https://box.kancloud.cn/e8a8b0e10f988fa8f378c82ce988a4d3_328x295.png) ![](https://box.kancloud.cn/ebc2b76edc4b74a2af6c8467d5f42029_309x137.png) ![](https://box.kancloud.cn/7cd0995681513657d79e52bf2f32fef7_281x117.png)