字节序Endian与字节序标记BOM详解
問(wèn)題引入
問(wèn):UTF-8 和 UTF-8-BOM 有啥區(qū)別?
我們用 Python 演示一下,帶與不帶 BOM 的字符串有啥區(qū)別。
if __name__ == '__main__':str = '你好啊樹哥'print('str:', str)str_encode_utf8 = str.encode('utf-8')print('str_encode_utf8:', str_encode_utf8)str_encode_utf8_bom = str.encode('utf-8-sig')print('str_encode_utf8_bom:', str_encode_utf8_bom)輸出結(jié)果顯示,帶 BOM 的比不帶的文本在開頭多了 ef bb bf 幾個(gè)字節(jié),為什么是這樣?它有什么用呢?
str: 你好啊樹哥 str_encode_utf8: b'\xe4\xbd\xa0\xe5\xa5\xbd\xe5\x95\x8a\xe6\xa0\x91\xe5\x93\xa5' str_encode_utf8_bom: b'\xef\xbb\xbf\xe4\xbd\xa0\xe5\xa5\xbd\xe5\x95\x8a\xe6\xa0\x91\xe5\x93\xa5'BOM 全稱 Byte Order Mark,字節(jié)順序標(biāo)記的意思,今天我們就來(lái)詳細(xì)聊聊它。
字節(jié)序
字節(jié)序(Endian),就是字節(jié)順序(Byte-Order),還叫端序或尾序(Endianness)。描述的是計(jì)算機(jī)對(duì) 多字節(jié)數(shù)據(jù) 存儲(chǔ)和傳輸時(shí)字節(jié)的順序。因?yàn)閱巫止?jié)的數(shù)據(jù)只需要讀取一個(gè)字節(jié),沒(méi)有字節(jié)序說(shuō)法。
字節(jié)序分為兩種排列模式,分別是大端字節(jié)序和小端字節(jié)序。
- 大端(Big-endian):高位字節(jié)數(shù)據(jù)存放在內(nèi)存低地址處,低位字節(jié)數(shù)據(jù)存放在內(nèi)存高地址處。大端模式比較符合人類的閱讀習(xí)慣,也這是人類讀寫數(shù)值的方式。
- 小端(Little-endian):高位字節(jié)數(shù)據(jù)存放在內(nèi)存高地址處,低位字節(jié)數(shù)據(jù)存放在內(nèi)存低地址處。由于計(jì)算機(jī)內(nèi)存數(shù)據(jù)處理是從低位開始的,因?yàn)樾《四J礁臃嫌?jì)算機(jī)的處理方式。
例如有 0x1234abcd 將它寫入到以 0x0000 開始的內(nèi)存中。
| Big-endian | 0x12 | 0x34 | 0xab | 0xcd |
| Little-endian | 0xcd | 0xab | 0x34 | 0x12 |
計(jì)算機(jī)默認(rèn)都是從低位開始讀,所以計(jì)算機(jī)內(nèi)部處理都是小端字節(jié)序。但人類習(xí)慣讀寫大端字節(jié)序,所以除了計(jì)算機(jī)的內(nèi)部處理,其他的應(yīng)用場(chǎng)合幾乎都是大端字節(jié)序,比如網(wǎng)絡(luò)傳輸和文件存儲(chǔ)。
- 主機(jī)字節(jié)序,Host Byte Order, HBO。指機(jī)器的字節(jié)序,有大端和小端模式,由機(jī)器的CPU處理器的處理決定,小端模式較為常見。
- 網(wǎng)絡(luò)字節(jié)序,Network Byte Order, NBO。是TCP/IP中規(guī)定好的一種數(shù)據(jù)表示格式,網(wǎng)絡(luò)字節(jié)序采用 Big Endian 排列按照從高到低的順序存儲(chǔ),在網(wǎng)絡(luò)上使用統(tǒng)一的網(wǎng)絡(luò)字節(jié)順序可以避免兼容性問(wèn)題。TCP/IP中規(guī)定好了一種數(shù)據(jù)表示格式,與具體的CPU類型、操作系統(tǒng)等無(wú)關(guān),從而保證數(shù)據(jù)在不同主機(jī)之間傳輸時(shí)能夠被正確解釋。
字節(jié)序標(biāo)記
BOM,全稱 Byte Order Mark,字節(jié)順序標(biāo)記。出現(xiàn)在文本文件頭部,用于標(biāo)識(shí)文件是采用哪種格式的編碼。
由于 FEFF 和 FFFE 在 UCS 編碼表中不存在(也就是說(shuō)它無(wú)實(shí)際意義),因此在字節(jié)流傳輸過(guò)程中可以利用它們打頭來(lái)說(shuō)明字節(jié)序。
- 如果接收者收到以 FEFF 開通的字節(jié)流,就表明這是 Big-Endian 的;
- 如果收到 FFFE 就表明這個(gè)字節(jié)流是 Little- Endian 的。
像 FEFF 和 FFFE 這種就稱作 Zero Width No-Break Space,翻譯過(guò)來(lái)就是 零寬無(wú)間斷間隔 ,這個(gè)字符就是所謂的 BOM。下面是不同編碼的字節(jié)順序標(biāo)記表示。
| UTF-8 | EF BB BF |
| UTF-16 (大端序) | FE FF |
| UTF-16(小端序) | FF FE |
| UTF-32 (大端序) | 00 00 FE FF |
| UTF-32 (小端序) | FF FE 00 00 |
總結(jié)幾點(diǎn)注意事項(xiàng)。
- UTF-8 本身不需要 BOM ,但可以使用它。UTF-8 始終是相同的字節(jié)順序,BOM 僅用于表明編碼方式。如果接收者收到以 EF BB BF 開頭的字節(jié)流,就知道這是 UTF-8編碼了。
- 以前字符 U+FEFF 出現(xiàn)在開頭就是標(biāo)識(shí)該字節(jié)流的字節(jié)序,如果出現(xiàn)在字節(jié)流的中間則表達(dá)零寬度非換行空格的意義,用戶看起來(lái)就是一個(gè)空格。從 Unicode 3.2 開始,U+FEFF 只能出現(xiàn)在字節(jié)流的開頭用于標(biāo)識(shí)字節(jié)序。取而代之的是,使用 U+2060 來(lái)表達(dá)零寬度無(wú)斷空白。
- 剛剛說(shuō)到的 U+FEFF 是代碼點(diǎn),抽象性質(zhì)的。而 EF BB BF ,FE FF,00 00 FE FF 則是在不同編碼方案下的具體表現(xiàn)形式。這是概念性的問(wèn)題。
參考
參考了
[1]. Endian
https://www.jianshu.com/p/a348f8fc9fc9
[2]. BOM (字節(jié)順序標(biāo)記(ByteOrderMark))
https://baike.baidu.com/item/BOM/2790364?fr=aladdin
[3]. 字節(jié)順序標(biāo)記(BOM)詳解
https://blog.csdn.net/gufenchen/article/details/90552774
[4]. 「帶 BOM 的 UTF-8」和「無(wú) BOM 的 UTF-8」有什么區(qū)別?網(wǎng)頁(yè)代碼一般使用哪個(gè)?
https://www.zhihu.com/question/20167122
總結(jié)
以上是生活随笔為你收集整理的字节序Endian与字节序标记BOM详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Tensorflow-制作与使用tfre
- 下一篇: python小作业初版之信用卡交易