2

我有以下代码以二进制方式将 ASCII“@”字符写入文件:

fin=open('a.bin','wb')
fin.write('\x40')
fin.close()

事实证明,“@”字符已写入长度为 1 字节的“a.bin”。

但是,当我尝试写一个 unicode 字符时:

fin=open('a.bin','wb')
fin.write(u'\x40')
fin.close()

原来“a.bin”仍然是 1 字节长。我认为它应该是 2 字节长,因为 unicode 字符需要 2 字节。我可能忽略了一些琐碎的事情。

4

3 回答 3

7

您将 Unicode 与编码混淆了。编码是将文本表示为 0-255(字节)范围内的单个值范围内的标准,而 Unicode 是描述表示文本字形的代码点的标准。两者有关联但不是一回事

Unicode 标准包括几种编码。UTF-16 就是这样一种编码,每个代码点使用 2 个字节,但它并不是标准中包含的唯一编码。UTF-8 是另一种这样的编码,它使用每个代码点的可变字节数。

但是,您的文件是使用 ASCII 编写的,它是您未指定显式编码时 Python 2 使用的默认编解码器。如果您希望看到每个代码点2个字节,请显式编码为 UTF-16:

fin.write(u'\x40'.encode('utf16-le')

这以little endian字节顺序写入 UTF-16 ;还有一个utf16-be编解码器。通常,对于 UTF-16 或 UTF32 等多字节编码,您还需要包含 BOM 或字节顺序标记;当您编写 UTF-16 而不选择任何字节序时,它会自动包含在内。

fin.write(u'\x40'.encode('utf16')

在继续之前,我强烈建议您学习 Unicode、编解码器和 Python:

于 2013-08-16T20:32:42.993 回答
1
  • 从 U+0000 到 U+007F(US-ASCII 曲目)的字符编号对应于八位字节 00 到 7F(7 位 US-ASCII 值)。一个直接的结果是纯 ASCII 字符串也是有效的 UTF-8 字符串。
  • UTF-8,一种 ISO 10646 的转换格式
于 2013-08-16T20:37:16.383 回答
1

Martijn 的详尽回答是正确的:首先了解有关 Unicode 的更多信息。但比阅读大型教育文档更小的答案可能是:

将 Python unicode 值(u'\x40'在您的情况下)写入流(在您的情况下为打开的文件)时,必须将此抽象 unicode 值转换为具体的字节流。为此使用了编码

您可以显式执行此操作(通过使用u'\x40'.encode('foo')),也可以隐式执行此操作;然后正在使用一些编码。在您的情况下,其中一个"ascii""utf8"两个都将 unicode-@ 表示为值为 40 的单个字节。

您似乎想要的是使用 unicode-@ 表示为两字节值的编码;例如,这将是编码utf-16

于 2013-08-16T22:03:56.837 回答