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

Chr*_* B. 10 python string codec

我有一个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中用内存表示原始二进制数据?
  • 当我通过编解码器写出原始二进制数据时,如何对其进行编码/取消编码?

Ben*_*kin 22

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

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

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

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

你想在输出文件中看到什么?

  • 如果文件应按原样包含二进制数据:

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

    • 如果你需要一个混合 UTF-8和原始二进制数据,你应该直接打开该文件,并混杂写some_datasome_text.encode('utf8')...

    但请注意,将UTF-8与原始任意数据混合是非常糟糕的设计,因为这样的文件非常不方便处理!理解unicode的工具会阻塞二进制数据,使您无法方便地查看(更不用说修改)文件.

  • 如果你想在unicode中友好地表示任意字节:

    传递data.encode('base64')给编解码器.Base64只生成干净的ascii(字母,数字和一点点标点符号),因此它可以清晰地嵌入到任何东西中,它清楚地将人们视为二进制数据,并且它相当紧凑(略高于33%的开销).

    PS你可能会注意到这data.encode('base64')很奇怪.

    • .encode()应该采取unicode,但我给它一个字符串?!Python有几个伪编解码器可以转换str-> 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,除非你明白为什么要这样做.
    我只是提到它是另一种"自然"编码.