
[英]Why is an empty string '' encoded into 2 bytes in utf-16 but 0 bytes in utf-8 or ascii?
[英]Is the [0xff, 0xfe] prefix required on utf-16 encoded strings?
我正在使用要求字符串的“ unicode編碼”的供應商設備,其中每個字符用兩個字節表示。 我的字符串將始終基於ASCII,因此我認為這是將字符串轉換為供應商字符串的方法:
>>> b1 = 'abc'.encode('utf-16')
但是檢查結果,我發現字節數組上有一個前導的[0xff,0xfe]:
>>> [hex(b) for b in b1]
['0xff', '0xfe', '0x61', '0x0', '0x62', '0x0', '0x63', '0x0']
由於供應商的設備不希望使用[0xff,0xfe],因此可以將其剝離...
>>> b2 = 'abc'.encode('utf-16')[2:]
>>> [hex(b) for b in b2]
['0x61', '0x0', '0x62', '0x0', '0x63', '0x0']
...這就是我想要的。
但是令我驚訝的是,我可以解碼b1和b2,並且它們都重新構造為原始字符串:
>>> b1.decode('utf-16') == b2.decode('utf-16')
True
所以我的兩個問題交織在一起:
這個觀察
...令我感到驚訝的是,我可以解碼b1和b2並將它們都重構為原始字符串:
b1.decode('utf-16') == b2.decode('utf-16') True
建議使用內置默認值,因為16位寬的UTF-16代碼有兩種可能的排列方式: Big和Little Endian 。
通常,Python會在讀取時從BOM推斷出要使用的字節序–因此在寫入時總是會加一。 如果要強制使用特定的字節序,則可以使用顯式編碼utf-16-le
和utf-16-be
:
…使用這種編碼時,BOM將自動寫為第一個字符,並且在讀取文件時將被靜默刪除。 這些編碼有多種變體,例如用於Little-endian和Big-endian編碼的'utf-16-le'和'utf-16-be',它們指定一個特定的字節順序並且不跳過BOM。
( https://docs.python.org/3/howto/unicode.html#reading-and-writing-unicode-data )
但是,如果您不使用特定的順序,那么將使用什么默認值? 原始Unicode提案PEP 100警告
注意:“ utf-16”應通過對文件輸入/輸出使用並要求使用字節序標記(BOM)來實現。
( https://www.python.org/dev/peps/pep-0100/ ,我的電話。)
但是它為您工作。 如果我們在Python源代碼中查找如何對其進行管理, _codecsmodule.c
在_codecsmodule.c
找到此注釋:
/* This version provides access to the byteorder parameter of the
builtin UTF-16 codecs as optional third argument. It defaults to 0
which means: use the native byte order and prepend the data with a
BOM mark.
*/
更深一層,在unicodeobject.c
,
/* Check for BOM marks (U+FEFF) in the input and adjust current
byte order setting accordingly. In native mode, the leading BOM
mark is skipped, in all other modes, it is copied to the output
stream as-is (giving a ZWNBSP character). */
因此,最初,字節順序被設置為系統的默認值,並且當您開始解碼UTF-16數據並且隨后出現BOM時,字節順序將被設置為此指定的值。 最后一條注釋中的“本機順序”是指是否已明確聲明某個字節順序,或者是否已通過BOM遇到; 當都不正確時,它將使用系統的字節序。
它是字節順序標記(又稱BOM):請參閱https://en.wikipedia.org/wiki/UTF-16 (請查看subheadin gByte順序編碼方案)。 目的是允許解碼器檢測編碼是小端還是大端。
它是用UTF-16編碼的Unicode字節順序標記。 其目的是將字節順序傳達給希望使用Unicode字符編碼進行編碼的文本的閱讀器。
如果讀者另外知道或開始知道字節順序,則可以忽略它。
'abc'.encode('utf-16-le')
答案,尤其是來自usr2564301的注釋, 將非常有用: 0xff 0xfe
前綴是“字節順序標記”,它帶有字節序信息和字節串。 如果知道所需的字節序,則可以指定utf-16-le
或utf-16-be
作為編碼的一部分。
這很清楚:
>>> 'abc'.encode('utf-16').hex()
'fffe610062006300'
>>> 'abc'.encode('utf-16-le').hex()
'610062006300'
>>> 'abc'.encode('utf-16-be').hex()
'006100620063'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.