簡體   English   中英

utf-16編碼的字符串是否需要[0xff,0xfe]前綴?

[英]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

所以我的兩個問題交織在一起:

  • 編碼字節頭上的0xff,0xfe有何意義?
  • 與上面的b2一樣,剝離0xff,0xfe前綴是否有任何危險?

這是字節順序標記 它是UTF文檔的前綴,用於指示文檔使用的字節序 它通過按字節順序對代碼點0xFEFF進行編碼來實現此目的-在這種情況下,為低位字節序(低有效字節在前)。 任何嘗試以另一種方式讀取它的方法(以大字節序(高字節在前))將讀取第一個字符為0xFFFE ,這是一個代碼點,該代碼點明確不是有效字符,從而通知讀者它需要進行錯誤或切換文件其余部分的字節序。

這個觀察

...令我感到驚訝的是,我可以解碼b1和b2並將它們都重構為原始字符串:

 b1.decode('utf-16') == b2.decode('utf-16') True 

建議使用內置默認值,因為16位寬的UTF-16代碼有兩種可能的排列方式: Big和Little Endian

通常,Python會在讀取時從BOM推斷出要使用的字節序–因此在寫入時總是會加一。 如果要強制使用特定的字節序,則可以使用顯式編碼utf-16-leutf-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-leutf-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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM