[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

相关文章
相关标签/搜索