【问题标题】:Encode Bytearray into UTF-8将 Bytearray 编码为 UTF-8
【发布时间】:2015-11-08 21:31:40
【问题描述】:

所以,在 Python 2.7 中我有一个字符串:

Python 2.7.8 (default, Apr 15 2015, 09:26:43) 
[GCC 4.9.2 20150212 (Red Hat 4.9.2-6)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import scrypt
>>> s=scrypt.encrypt('somestring', 'test'.encode('ascii'), 0.1)
>>> s
'scrypt\x00\r\x00\x00\x00\x08\x00\x00\x00\x016 \xf2\xcc\xf9\xd2\xbe\xd4\xdbU!\xaf\xecKk{\x8b\r\x94\xe8\x11\xf2\x00\x1f\xd9\xceBhf$cM\x12{\xd8\x84\\\xf2j`\xba\xc5Xk\x196)\xf5\xd3\xe9\x15\xdd\xd3\xa0A_K\x00\x18\x03J\x85\xee\n\xcc\xea\x86\xda\xaa\xfd6E\xf4\x804\xfe\x04\xca\xec!\x94F\x84)B\tf\x07\xd9!@B,\x9e\xffc\xf2\xb6e\x8c\xa9HA\x98\x99\xa0\xe8\xcf\x85P2\x13\x0f\xa1\xf6\x90nO\x85Z\xb2\xc1'
>>> type(s)
<type 'str'>

(真的很丑。)

我需要将其编码为文本 - 一个 unicode 对象或一个 utf-8 字符串。

TypeError: You are required to pass either a unicode object or a utf-8 string here.
You passed a Python string object which contained non-utf-8:
'scrypt\x00\r\x00\x00\x00\x08\x00\x00\x00\x01\xce\xf5\xba\x19\xeb1z/5*`m\xec\xf6sgT4\xb5.\xf7^\x96\xfaMY6\xa0\xdb\t\xa3*<5A<\xfb\xbe\xfb>w\xa3,MjaX;\xc1r\xdc\xbd\x04W\xafq3O\x90\x19!\x13\xe8\x0c\x86\xf5\xc96\xf4K\x16\xe3^.v\x8a\xe0\xda\xdd>#\xa7\\\x1c\xc2\x11\x85\x01\xb5\xd4\x92\xef\xa1k\x05Z\xaey\xd7M`%5.\x9f\xb1\xc4\x11N\xdeY\xa2\xac=\r\n\xb4aM\xfd)\xcc$\xbbq\xaa\xfd\x9d \xa5\xd39|\x85\xc8\x95\xbc\xfa\x17\xa1\x8e\xb8\x81 \xb4\x9b>j'.
The UnicodeDecodeError that resulted from attempting to interpret it as utf-8 was:
'utf8' codec can't decode byte 0xce in position 20: invalid continuation byte

问题是,它超出了 UTF-8 的范围:

>>> s.encode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf2 in position 18: ordinal not in range(128)

那么:我应该如何对这个字符串进行编码?

如果您能告诉我为什么ascii 编解码器在我尝试编码 一个字符串时出现错误(以及所有事物中的UnicodeDecodeError),则可以加分。

(为了记录,尝试编码为 UTF-16 会引发完全相同的错误。)

我已经让它与 base64 一起工作(我想这就是它的用途),但我很好奇为什么会出现这个错误以及我的选择是什么。

【问题讨论】:

  • 你有二进制数据。不是文本,当然也不是 Unicode。您不能将此编码为 UTF-8,因为它不是 unicode(文本)对象。为什么你认为你需要对此进行编码?
  • 绝对加密它并把它扔到互联网上。那会很可疑。 ;)
  • (真正的)加密算法适用于字节,而不是文本。
  • 您的错误是由 Python 尝试先解码数据引起的;它试图提供帮助,因为通常您只能编码 Unicode。由于您尝试对字节执行此操作,因此它首先需要将字节解码为 Unicode,然后使用 ASCII 编解码器来完成。
  • 如果可以,考虑升级到 Python 3。它在文本和原始字节之间保持更严格的分隔,最明显的影响之一是调用 str.encode 不能触发 @ 987654328@.

标签: python python-2.7 unicode utf-8 character-encoding


【解决方案1】:

你有二进制数据。不是文本,当然也不是 Unicode。您不能将此编码为 UTF-8,因为它不是 unicode(文本)对象。

您的UnicodeDecodeError 是由Python 尝试首先解码 数据引起的;它试图提供帮助,因为通常您只能从 Unicode 编码为字节。由于您尝试对字节执行此操作,因此它首先需要将字节解码为 Unicode,并且它将使用 ASCII 编解码器来执行此操作。但是您没有 ASCII 数据,也没有任何其他文本编码。

您不能从这些字节中生成 Unicode,因为它不是文本。您唯一的选择是使用像 base64 这样的二进制到文本方案,它以安全的方式包装二进制数据,以便通过需要文本的系统进行传输(因此不支持 \x00 NUL 字节或 \x0a 换行符或其他具有文本流中的特殊含义。

请参阅binascii library,了解 Python 标准库中可用的各种二进制到文本的方案; base64 是其中使用最广泛的。

【讨论】:

    【解决方案2】:

    一般的答案是您不能 - 您的通用二进制数据可能包含根本不是有效 utf-8 的字节序列。但是,根据您的应用程序,也许您可​​以使用 Base 64 等二进制转文本编码将数据存储在您需要的任何位置,然后在检索时对其进行解码?

    参考: https://en.wikipedia.org/wiki/Base64

    https://docs.python.org/2/library/base64.html

    【讨论】:

    • 正如我在问题中提到的,我已经让它与 base64 一起使用,但我对错误消息、它的含义以及除 b64 之外的其他选项(如果有的话)更好奇。
    猜你喜欢
    • 2012-04-24
    • 2012-08-16
    • 1970-01-01
    • 2012-06-30
    • 2017-08-23
    • 2015-10-02
    • 2013-06-02
    • 2011-08-09
    • 2011-06-26
    相关资源
    最近更新 更多