如何在Python中编写原始二进制数据?

时间:2010-04-09 21:58:07

标签: python codec string

我有一个Python程序,用于存储数据并将数据写入文件。数据是原始二进制数据,内部存储为str。我是通过utf-8编解码器写出来的。但是,我在UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 25: character maps to <undefined>文件中获得cp1252.py

这让我觉得Python正在尝试使用默认代码页来解释数据。但它没有默认代码页。这就是为什么我使用的是str,而不是unicode

我想我的问题是:

  • 如何用Python表示内存中的原始二进制数据?
  • 当我通过编解码器写出原始二进制数据时,如何对其进行编码/取消编码?

3 个答案:

答案 0 :(得分:22)

注意:这是为Python 2.x编写的。不确定是否适用于3.x。

您在内存中使用str原始二进制数据是正确的 [如果您使用的是Python 2.6+,最好使用bytes,它在2.6+中只是str的别名,但更好地表达了您的意图,如果有一天您将代码移植,将会有所帮助到Python 3。]

正如其他人所说,通过编解码器写二进制数据很奇怪。写入编解码器将unicode 输出字节带入文件。你试图向后做,因此我们对你的意图感到困惑......

[并且您对错误的诊断看起来是正确的:因为编解码器需要unicode,所以Python会使用系统的默认编码将您的str解码为unicode,这会阻塞。]

您希望在输出文件中看到什么?

  • 如果文件应包含二进制数据

    然后你不能通过编解码器发送它;你必须写它 直接到文件。编解码器编码所有内容并且只能编码 发出有效的unicode编码(在您的情况下,有效的UTF-8)。 没有任何输入你可以让它使它发出任意 字节序列!

    • 如果您需要UTF-8和原始二进制数据的混合,那么您 应直接打开文件,并混合some_data的写入 与some_text.encode('utf8') ...

    但请注意,将UTF-8与原始任意数据混合非常 糟糕的设计,因为这样的文件处理起来非常不方便 有!理解unicode的工具会阻塞二进制文件 数据,让你用不方便的方式来查看(更不用说了 修改)文件。

  • 如果你想要一个友好的任意字节表示 的unicode

    data.encode('base64')传递给编解码器。 Base64仅生产 干净的ascii(字母,数字和一点点标点)所以它 它可以清楚地嵌入任何东西中,它清楚地看作是人们的 二进制数据,它相当紧凑(略高于33%) 开销)。

    P.S。您可能会注意到data.encode('base64')很奇怪。

    • .encode()应该采取unicode,但我给它一个 串?! Python有几个转换str-&gt; str的伪编解码器 例如'base64'和'zlib'。

    • .encode()始终返回一个str,但您会将其输入编解码器 期待unicode?!在这种情况下,它只包含干净 ascii,所以没关系。你可以明确写 data.encode('base64').encode('utf8')如果它让你感觉到 更好。

  • 如果您需要从任意字节到unicode的1:1映射

    data.decode('latin1')传递给编解码器。 latin1地图 字节0-255为unicode字符0-255,这有点优雅。

    编解码器当然会对你的角色进行编码 - 128-255 在UTF-8中编码为2或3个字节(令人惊讶的是,平均值 开销是50%,超过base64!)。这完全杀了 具有1:1映射的“优雅”。

    另请注意,unicode字符0-255包含令人讨厌的内容 隐形/控制字符(换行符,换页符,软连字符等) 使您的二进制数据烦人,无法在文本编辑器中查看。

    考虑到这些缺点,我不建议使用latin1 ,除非 你完全理解为什么要这样。
    我只是提到它是另一种“自然”编码 记住。

答案 1 :(得分:0)

您通常不应将编解码器与str一起使用,除非将它们转换为unicode。如果你认为你想在你的unicodes中想要“原始”数据,也许你应该考虑使用latin-1编解码器。

答案 2 :(得分:0)

对于你的第一个问题:在Python中,常规字符串(即不是unicode字符串)是二进制数据。如果要编写unicode字符串和二进制数据,请将unicode字符串转换为二进制数据并将它们放在一起:

# encode the unicode string as a string
bytes = unicodeString.encode('utf-8')
# add it to the other string
raw_data += bytes
# write it all to a file
yourFile.write(raw_data)

关于第二个问题:你write()原始数据;然后,当你阅读它时,你会这样做:

import codecs
yourFile = codecs.open( "yourFileName", "r", "utf-8" )
# and now just use yourFile.read() to read it