我有一个 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 中表示内存中的原始二进制数据?
- 当我通过编解码器写出原始二进制数据时,我该如何对其进行编码/取消编码?
最佳答案
注意:这是为 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 的工具会阻塞二进制文件 数据,让您无法方便地查看(更不用说 修改)文件。
- 如果您需要 UTF-8 和原始二进制数据的混合,您
应该直接打开文件,并混合写入
如果你想要一个友好的任意字节的表示 统一码:
将
data.encode('base64')
传递给编解码器。 Base64 只产生 干净的 ascii(字母、数字和一些标点符号)所以它 可以清楚地嵌入到任何东西中,它在人们看来显然是 二进制数据,它相当紧凑(略高于 33% 开销)。附言您可能会注意到
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
map 字节 0-255 到 unicode 字符 0-255,这有点优雅。编解码器当然会对您的字符进行编码 - 128-255 是 在 UTF-8 中编码为 2 或 3 个字节(令人惊讶的是,平均 开销是 50%,比 base64 多!)。这完全杀死了 具有 1:1 映射的“优雅”。
另请注意,unicode 字符 0-255 包括讨厌的字符 不可见/控制字符(换行符、换页符、软连字符等) 使您的二进制数据在文本编辑器中查看很烦人。
考虑到这些缺点,我不推荐latin1,除非 你完全明白你为什么想要它。
我只是提到它是另一种“自然”编码 记住。
关于python - 如何用 Python 编写原始二进制数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2611205/