我需要在python中保存一个params文件,并且此params文件包含一些我不会在纯文本上保留的参数,因此我将整个文件编码为base64(我知道这不是最安全的编码世界,但它适用于我需要使用的那种数据。
使用编码,一切工作正常。我对文件的内容进行编码(带有适当扩展名的简单txt)并保存文件。问题在于解码。我打印了保存文件之前编码的文本和保存文件中编码的文本,它们完全相同,但是由于我不知道的原因,对保存文件的文本进行解码会返回此错误{{1 }},然后在保存文件之前对文本进行解码即可。
有解决此问题的主意吗?
这是我的代码,我尝试将所有内容都转换为字节,字符串以及所有内容...
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8d in position 1: invalid start byte
答案 0 :(得分:3)
您的错误在于处理bytes
返回的base64.b64encode()
对象,您在对象上调用了str()
:
newparams.write(str(paramsencoded))
该{em>不解码 bytes
对象:
>>> bytesvalue = b'abc='
>>> str(bytesvalue)
"b'abc='"
请注意b'...'
表示法。您生成了bytes对象的 representation ,这是一个包含Python语法的字符串,该字符串可以为调试目的而复制该值(您可以复制该字符串值并将其粘贴到Python中以重新创建相同的{值{1}}。
乍一看可能不太容易,因为bytes
否则只会生成带有可打印ASCII字节的输出。
但是您的解码问题是从那里开始的,因为在解码时,从文件读取的值在开始时包含base64.b64encode()
个字符。前两个字符被解释为Base64数据 ; b'
是有效的Base64字符,解析器将忽略b
:
'
请注意输出结果完全不同,因为Base64解码现在从错误的位置开始,因为>>> bytesvalue = b'hello world'
>>> base64.b64encode(bytesvalue)
b'aGVsbG8gd29ybGQ='
>>> str(base64.b64encode(bytesvalue))
"b'aGVsbG8gd29ybGQ='"
>>> base64.b64decode(str(base64.b64encode(bytesvalue))) # with str()
b'm\xa1\x95\xb1\xb1\xbc\x81\xdd\xbd\xc9\xb1\x90'
>>> base64.b64decode(base64.b64encode(bytesvalue)) # without str()
b'hello world'
是第一个字节的前6位(使第一个解码后字节6C,6D,6E或6F字节,因此b
,m
,n
或o
ASCII)。
您可以正确地解码值(使用p
或paramsencoded.decode('ascii')
),但是您不应将任何这些数据都视为文本。
相反,请以 binary模式打开文件。然后使用str(paramsencoded, 'ascii')
对象进行读写操作,并且bytes
和base64.b64encode()
函数也可以在base64.b64decode()
上进行操作,从而实现完美的匹配:
bytes
我明确使用with open('params.bpr', 'rb') as params_source:
params = params_source.read() # bytes object
params_encoded = base64.b64encode(params)
print(params_encoded.decode('ascii')) # base64 data is always ASCII data
params_decoded = base64.b64decode(params_encoded)
with open('paramsencoded.bpr', 'wb') as new_params:
newparams.write(params_encoded) # write binary data
with open('paramsencoded.bpr', 'rb') as new_params:
params_written = new_params.read()
print(params_written.decode('ascii')) # still Base64 data, so decode as ASCII
params_decoded = base64.b64decode(params_written) # decode the bytes value
print(params_decoded.decode('utf8')) # assuming the original source was UTF-8
而不是bytes.decode(codec)
来避免意外的str(..., codec)
呼叫。