[NodeJs系列]聊一聊BOM

若是你對NodeJs系列感興趣,歡迎關注微信公衆號:前端神盾局或 github NodeJs系列文章前端

最近在看Node源碼的時候,偶然間,看到以下函數:git

/**
 * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
 * because the buffer-to-string conversion in `fs.readFileSync()`
 * translates it to FEFF, the UTF-16 BOM.
 */
function stripBOM(content) {
  if (content.charCodeAt(0) === 0xFEFF) {
    content = content.slice(1);
  }
  return content;
}

對於函數的功能,註釋寫的很清楚了-用於清除字節序標識符(BOM)。github

對於BOM,相信大多數人對其即陌生又熟悉,咱們在各大IDE中經常見到它的身影,但要真的把它解釋清除,卻有點力不從心。故此,筆者利用閒暇之餘搜索資料整理成文,若是錯漏,還望提點!微信

字節序

在解釋BOM以前,咱們不得不提到字節序。函數

在古時,咱們的不少書刊保有從左到右的排版的習慣。即便是今天,某些國家的文字讀序依舊存在差別。計算機世界也是如此。編碼

咱們把多字節排練的順序叫作字節序。spa

這裏咱們經過一個例子展開說明(本例來自:「字節序」是個什麼鬼?):code

給定兩個分別須要4個字節存儲的整數,爲了方便說明,使用16進製表示這兩個數,即0x12345678和0x11223344。對於如何存儲,有人提了兩個方案:blog

方案一:進程

image

方案二:

image

對於方案一,高位字節在存儲在高位地址,低位字節在低位地址,咱們稱之爲大端(Big endian)字節序。方案二把低位字節在前,高位字節在後,咱們把這種順序叫作小端(Little endian)字節序。

BOM

對於人類而言,字節序也許並非問題。好比從右往左讀"字節序",聰明如大家,會發現「序節字」根本語義不通,能夠輕鬆的找到解決之道。但對於計算機而言,它不明白什麼是語義,也無法聯繫上下文。它只能按照給定的指令去讀取字節。若是是大端字節序,先讀到的就是高位字節,後讀到的就是低位字節。小端字節序正好相反。

因此對於計算機而言,咱們須要一種方法去標識字節序,以防亂碼的出現。BOM就是一種用於標識的unicode字符,它常被用來當作標示以UTF-八、UTF-16或UTF-32爲編碼的文件

對於UTF-16和UTF-32而言,由於他們分別使用2個字節和4個字節編碼Unicode字符,對於多字節編碼,BOM的存在顯然頗有必要。此時BOM被放置爲文件或字符串流的第一個字符,若是標識符爲U+FFFE則表示大端字節序,若是標識符爲U+FEFF則表示小端字節序。

那既然BOM是用於標示字節序的,那爲何還要把它刪除呢?這裏就不得不提一下UTF-8了。

UTF-8是一種可變字節長度的編碼方式(最小1字節,最大4字節),也就是說UTF-8能夠根據數據大小來決定要存儲的字節數。它的編碼方式與其餘二者不一樣,無需使用BOM。

UTF-8在首字節標識了字節的個數。若是首字節以0開頭,則表明單字節編碼,若是以110開頭者表示該字節爲兩個字節中的第一個字節,以此類推。除了單字節外,多字節UTF-8碼的後續字節均以10開頭。

因此1~4字節UTF-8編碼看起來是這樣的:

0xxxxxxx
110xxxxx 10xxxxxx
1110xxxx 10xxxxxx 10xxxxxx
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

So BOM 在UTF-8編碼中是非必須的,在類Unix系統(大量使用文本文件,用於文件格式,用於進程間通訊)中,這種作法(插入BOM)是不被建議採用,由於它會妨礙到如解譯器腳本開頭的Shebang等的正確處理,可是許多視窗程序(包含記事本)會須要添加字節順序標記到UTF-8文件。

參考

  1. 「字節序」是個什麼鬼?
  2. 爲何UTF-8沒有字節序問題?
  3. Unicode字符集與UTF-8編碼
  4. 字節順序標記

image

相關文章
相關標籤/搜索