字节序Endian与字节序标记BOM详解
問題引入
問: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 幾個字節(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)記的意思,今天我們就來詳細聊聊它。
字節(jié)序
字節(jié)序(Endian),就是字節(jié)順序(Byte-Order),還叫端序或尾序(Endianness)。描述的是計算機對 多字節(jié)數(shù)據(jù) 存儲和傳輸時字節(jié)的順序。因為單字節(jié)的數(shù)據(jù)只需要讀取一個字節(jié),沒有字節(jié)序說法。
字節(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)存低地址處。由于計算機內(nèi)存數(shù)據(jù)處理是從低位開始的,因為小端模式更加符合計算機的處理方式。
例如有 0x1234abcd 將它寫入到以 0x0000 開始的內(nèi)存中。
| Big-endian | 0x12 | 0x34 | 0xab | 0xcd |
| Little-endian | 0xcd | 0xab | 0x34 | 0x12 |
計算機默認都是從低位開始讀,所以計算機內(nèi)部處理都是小端字節(jié)序。但人類習(xí)慣讀寫大端字節(jié)序,所以除了計算機的內(nèi)部處理,其他的應(yīng)用場合幾乎都是大端字節(jié)序,比如網(wǎng)絡(luò)傳輸和文件存儲。
- 主機字節(jié)序,Host Byte Order, HBO。指機器的字節(jié)序,有大端和小端模式,由機器的CPU處理器的處理決定,小端模式較為常見。
- 網(wǎng)絡(luò)字節(jié)序,Network Byte Order, NBO。是TCP/IP中規(guī)定好的一種數(shù)據(jù)表示格式,網(wǎng)絡(luò)字節(jié)序采用 Big Endian 排列按照從高到低的順序存儲,在網(wǎng)絡(luò)上使用統(tǒng)一的網(wǎng)絡(luò)字節(jié)順序可以避免兼容性問題。TCP/IP中規(guī)定好了一種數(shù)據(jù)表示格式,與具體的CPU類型、操作系統(tǒng)等無關(guān),從而保證數(shù)據(jù)在不同主機之間傳輸時能夠被正確解釋。
字節(jié)序標(biāo)記
BOM,全稱 Byte Order Mark,字節(jié)順序標(biāo)記。出現(xiàn)在文本文件頭部,用于標(biāo)識文件是采用哪種格式的編碼。
由于 FEFF 和 FFFE 在 UCS 編碼表中不存在(也就是說它無實際意義),因此在字節(jié)流傳輸過程中可以利用它們打頭來說明字節(jié)序。
- 如果接收者收到以 FEFF 開通的字節(jié)流,就表明這是 Big-Endian 的;
- 如果收到 FFFE 就表明這個字節(jié)流是 Little- Endian 的。
像 FEFF 和 FFFE 這種就稱作 Zero Width No-Break Space,翻譯過來就是 零寬無間斷間隔 ,這個字符就是所謂的 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é)幾點注意事項。
- UTF-8 本身不需要 BOM ,但可以使用它。UTF-8 始終是相同的字節(jié)順序,BOM 僅用于表明編碼方式。如果接收者收到以 EF BB BF 開頭的字節(jié)流,就知道這是 UTF-8編碼了。
- 以前字符 U+FEFF 出現(xiàn)在開頭就是標(biāo)識該字節(jié)流的字節(jié)序,如果出現(xiàn)在字節(jié)流的中間則表達零寬度非換行空格的意義,用戶看起來就是一個空格。從 Unicode 3.2 開始,U+FEFF 只能出現(xiàn)在字節(jié)流的開頭用于標(biāo)識字節(jié)序。取而代之的是,使用 U+2060 來表達零寬度無斷空白。
- 剛剛說到的 U+FEFF 是代碼點,抽象性質(zhì)的。而 EF BB BF ,FE FF,00 00 FE FF 則是在不同編碼方案下的具體表現(xià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」和「無 BOM 的 UTF-8」有什么區(qū)別?網(wǎng)頁代碼一般使用哪個?
https://www.zhihu.com/question/20167122
總結(jié)
以上是生活随笔為你收集整理的字节序Endian与字节序标记BOM详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Tensorflow-制作与使用tfre
- 下一篇: 认知天性个人笔记6