繁体   English   中英

utf-16编码的字符串是否需要[0xff,0xfe]前缀?

Is the [0xff, 0xfe] prefix required on utf-16 encoded strings?

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

改写问题!

我正在使用要求字符串的“ 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前缀是否有任何危险?
5 个回复

这是字节顺序标记 它是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'
2 如何在utf-16中编码JavaScript字符串?

在Python 3中,我可以这样做: 输入是一个(unicode)字符串,而输出是该字符串的原始字节序列,该字符串以utf-16编码。 如何在JavaScript中做同样的事情-从一个(unicode)字符串到以utf-16编码的那个字符串的原始字节序列(也许是Uint8Array ...

3 将UTF-16编码的字符串解析为xml

我有一个要用php解析的UTF-16编码的xmlstring。 无法编码为UTF-8因为并非所有内容都可以用UTF-8表示 问题是,当我尝试使用xml_parser_create("UTF-16")和xml_parse_into_struct函数时,我收到有关不支持UTF-16的消息。 ...

4 char16_t字符串必须使用UTF-16编码吗?

我一直在挖掘规范一段时间,但找不到支持是/否的任何结论性条款。 请注意以下内容: 暗示/强制字符串文字“asdf”必须以UTF-16编码? 从我可以推断的一切,这是肯定的。 但是,在这个提议n2018中 ,只有在定义了“ __STDC_UTF_16__ ”时, char ...

6 如何使用UTF-8编码UTF-16转换xml字符串?

例如,假设我在字符串中有以下xml: 如果我尝试将其插入带有Xml列的SQL Server 2005数据库表中,我将收到以下错误(我使用的是EF 4.1,但我认为不重要): XML解析:第1行,第38个字符,无法切换编码 在做了一些研究之后,我了解到SQL Server ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM