那些年,遇到的亂碼

  • pre-notify
  • Node.js支持的編碼
  • gb2312
  • utf8和隱藏在黑夜中的兇手
  • BOM
    • BOM的真面目
    • 幹掉BOM!
  • 讓node支持gbk——iconv-lite
  • string_decoder

pre-notify

本文會不斷完善,也歡迎各位大佬一塊兒「打磨」node

Node.js支持的編碼

當咱們讀一個文件的時候,能夠指定以什麼樣的編碼來讀取web

fs.readFile('./test.txt','utf8',function(err,data){
    console.log(data); //打印出來的就是編碼後的字符串
})
複製代碼

注意:bash

  • Node.js默認支持的編碼有utf八、base64,不支持gb系列
  • 不填寫編碼時,默認數據的形式是buffer

gb2312

當咱們在桌面建立一個.txt時,默認編碼是gb2312,而又因爲Node.js默認是不支持的,So咱們經過fs讀取到的buffer是轉換不成咱們想要的中文文字的。 webstorm

大多數編輯器打開這些文件時候也會亂碼。

[warning] 注意: 即便將txt文件的後綴名更改成.js也是同樣的。編輯器

utf8和隱藏在黑夜中的兇手

咱們能夠將文本另存爲utf8ui

這樣雖然能讓中文正常顯示,但咱們發如今開始的位置卻出現了亂碼。 編碼

這是爲何呢?spa

在咱們使用unicode系編碼的時,由於unicode編碼有不少實現,So它會籤個名,表示這個文件的是utf8編碼的,歸utf8管。這樣咱們再使用編輯器打開的時候它就不會亂碼code

what?! 編輯器打開都不亂碼了,你娃娃node.js讀文件toString還要亂碼?orm

腳多麻的,讓咱們換一個編輯器,嗯,webstorm

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());
複製代碼
相關文章
相關標籤/搜索