将二进制数据转换为Web安全文本并返回 - Python

时间:2011-10-23 19:26:29

标签: python file binary ascii utf

我想将二进制文件(例如jpg,mp3等)转换为Web安全文本,然后再转换为二进制数据。我已经研究了几个模块,我认为我非常接近,但我一直在弄乱数据。

在查看binascii的文档后,我提出了这个问题:

from binascii import *
raw_bytes = open('test.jpg','rb').read()
text = b2a_qp(raw_bytes,quotetabs=True,header=False)
bytesback = a2b_qp(text,header=False)
f = open('converted.jpg','wb')
f.write(bytesback)
f.close()

当我尝试打开converted.jpg时,我收到数据损坏: - /

我还尝试使用b2a_base64和57长的二进制数据块。我把每个块转换成一个字符串,将它们连接在一起,然后转换回a2b_base64并再次腐败。

有人可以帮忙吗?我对所有复杂的字节和文件格式都不是很了解。我在Windows上使用Python,如果这对\r\n内容产生影响

4 个答案:

答案 0 :(得分:1)

您应该使用base64编码而不是quoted printable。使用b2a_base64()a2b_base64()

对于像图片这样的二进制数据,引用的可打印要大得多。在此编码中,每个二进制(非字母数字字符)代码都将更改为=HEX。它可用于主要由电子邮件主题等字母数字组成的文本。

对于主要的二进制数据,Base64要好得多。它需要6个第一个字节的位,然后是第1个字节的最后2位和第2个字节的4个位。它可以通过编码文本末尾的=填充来识别(有时使用其他字符)。

作为一个例子,我拿了271 700字节的.jpeg。在qp中它是627 857 b,而在base64中它是362 269字节。 qp的大小取决于数据类型:仅为字母的文本不会更改。 base64的大小为orig_size * 8 / 6

答案 1 :(得分:1)

您的文档参考适用于Python 3.0.1。使用Python 3.0没有充分的理由。你应该使用3.2或2.7。你究竟在用什么?

建议:(1)将bytes更改为raw_bytes,以避免与bytes == raw_bytes的{​​{1}}内置(2)检查混淆在您的测试脚本(3)中,当您的测试应该使用quoted-printable时,二进制数据的效率非常低;改为使用base64。

更新:Base64编码为每3个输入字节产生4个输出字节。你的base64代码不适用于56字节的块,因为56不是3的整数倍;每个块被填充到3的倍数。然后你加入块并尝试解码,这保证不起作用。

你的分块循环会写得更好:

bytes_back

无论如何,分块相当缓慢而毫无意义;只需output_string = ''.join( b2a_base64(raw_bytes[i:i+57]) for i in xrange(0, xrange(len(raw_bytes), 57) )

答案 2 :(得分:1)

您的代码看起来很复杂。试试这个:

#!/usr/bin/env python

from binascii import *
raw_bytes = open('28.jpg','rb').read()
i = 0
str_one = b2a_base64(raw_bytes) # 1
str_list = b2a_base64(raw_bytes).split("\n") #2

bytesBackAll = a2b_base64(''.join(str_list)) #2
print bytesBackAll == raw_bytes #True #2

bytesBackAll = a2b_base64(str_one) #1
print bytesBackAll == raw_bytes #True #1

标有#1#2的行代表彼此的替代方案。 #1对我来说似乎最直接 - 只需将其设为一个字符串,处理它并将其转换回来。

答案 3 :(得分:-2)

@ PMC的答案是从问题中复制出来的:

这是有效的:

from binascii import *
raw_bytes = open('28.jpg','rb').read()
str_list = []
i = 0
while i < len(raw_bytes):
    byteSegment = raw_bytes[i:i+57]
    str_list.append(b2a_base64(byteSegment))
    i += 57
bytesBackAll = a2b_base64(''.join(str_list))
print bytesBackAll == raw_bytes #True

感谢帮助人员。我不知道为什么会因为[0:56]而不是[0:57]而失败,但我会将其作为练习留给读者:P