python 二进制文件转文本文件_【Python】二进制文件与Base64编码文本文件转换

前面的话

Python内置的base64模块,在这里http://docs.python.org/library/base64.html?highlight=base64#base64,包括b64encode,b64decode,urlsafe_b64decode等,可以满足包括URL在内的文本编码需要。但是在用base64.encode编码二进制文件的时候,发现编码不完整,只有部分文件被编码了,base64.decode解码出来文件错误。可能是base64模块用来出来文本的?仔细分析发现,是忘记用二进制模式打开文件了。但是,自己实现base64模块基本功能也不是什么难事,不是要重复发明轮子,仅作为学习python和base64的练习。

用内置 base64模块转换二进制文件与base64编码文本文件方法如下:import base64

fin = open(r"D:\2.zip", "rb")

fout = open(r"D:\2.x.txt", "w")

base64.encode(fin, fout)

fin.close()

fout.close()

fin = open(r"D:\2.x.txt", "r")

fout = open(r"D:\2.x.zip", "wb")

base64.decode(fin, fout)

fin.close()

fout.close()

Base64介绍

Base64是一种基于64个可打印字符来表示二进制数据的表示方法。Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据。包括MIME的email,email

via MIME, 在XML中存储复杂数据。

转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不足3byte的话,于缓冲区中剩下的bit用0补足。然后,每次取出6(因为)个bit,按照其值选择ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。

如果最后剩下两个输入数据,在编码结果后加1个“=”;如果最后剩下一个输入数据,编码结果后加2个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。

Base64索引表:

ValueCharValueCharValueCharValueChar

0A16Q32g48w

1B17R33h49x

2C18S34i50y

3D19T35j51z

4E20U36k520

5F21V37l531

6G22W38m542

7H23X39n553

8I24Y40o564

9J25Z41p575

10K26a42q586

11L27b43r597

12M28c44s608

13N29d45t619

14O30e46u62+

15P31f47v63/

二进制转成Base64编码

按照算法描述:

1、讲输入数据按3个字节组成一组3*8=24位的整数;

2、然后将其按6位一组分为24/6=4组;

3、每组6位算出取值,在base64索引表中查看对应的字符,即可;

4、如果还有模3剩余的1个字节数据,则补2个字节的0,将转换成的4字符的最后2个替换成”==”;

5、如果还有模3剩余的2个字节数据,则补1个字节的0,将转换成的4字符的最后1个替换成”=”。

其中1-3步容易理解和编写,第4、5步的实现方法可能有很多种,但是考虑到可读性,而且每次转换之多执行其中一步,可以使用如下中的硬编码:_CODE_CHAR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

def binbase64(data):

"""

Convert binary data to Base64 format string.

"""

base64str = ""

for i in range(len(data)/3):

datavalue = ((data[3*i] << 16) | (data[3*i+1] << 8) | data[3*i+2])

for j in range(4):

base64str += _CODE_CHAR[(datavalue >> 6*(3-j)) & 0x3F]

dataremain = len(data) % 3

if dataremain == 1:

datavalue = data[-1] << 16;

base64str += _CODE_CHAR[(datavalue >> 18) & 0x3F]

base64str += _CODE_CHAR[(datavalue >> 12) & 0x3F]

base64str += "=="

elif dataremain == 2:

datavalue = (data[-2] << 16) | (data[-1] << 8);

base64str += _CODE_CHAR[(datavalue >> 18) & 0x3F]

base64str += _CODE_CHAR[(datavalue >> 12) & 0x3F]

base64str += _CODE_CHAR[(datavalue >> 6) & 0x3F]

base64str += "="

return base64str

Base64解码转成二进制

解码之前要对输入数据有效性进行必要的判断,如长度是否为4的整数倍,有没有非法字符等。解码步骤为:

1、取4个字符组成一组,判断每个字符在Base64索引表中的索引值;

2、将索引值转成6位二进制,并组4*6=24位的整数;

3、再将这个24位的整数分成24/8=3个字节;

4、如果末尾有2个"==",则只有1个有效字节

5、如果末尾有1个"=",在有2个有效字节def base64bin(encodedstr):

"""

Convert Base64 format string to binary data.

"""

if len(encodedstr) % 4:

raise Base64Error("The length of input 'base64str' MUST be multiple of 4.")

rawbase64str = encodedstr.rstrip("=")

if (len(rawbase64str) % 4) == 1:

raise Base64Error("Too many '=' characters, MUST NOT be more than 2.")

for x in rawbase64str:

if x not in _CODE_CHAR:

raise Base64Error("Unexpected character %s.", x)

data=[]

for i in range(len(rawbase64str)/4):

datavalue = (_CODE_CHAR.find(rawbase64str[4*i]) << 18) \

| (_CODE_CHAR.find(rawbase64str[4*i+1]) << 12) \

| (_CODE_CHAR.find(rawbase64str[4*i+2]) << 6) \

| (_CODE_CHAR.find(rawbase64str[4*i+3]))

data.append((datavalue >> 16) & 0xFF)

data.append((datavalue >> 8) & 0xFF)

data.append((datavalue) & 0xFF)

strremain = len(rawbase64str) % 4

if strremain == 2:

datavalue = (_CODE_CHAR.find(rawbase64str[-2]) << 18) \

| (_CODE_CHAR.find(rawbase64str[-1]) << 12)

data.append((datavalue >> 16) & 0xFF)

elif strremain == 3:

datavalue = (_CODE_CHAR.find(rawbase64str[-3]) << 18) \

| (_CODE_CHAR.find(rawbase64str[-2]) << 12) \

| (_CODE_CHAR.find(rawbase64str[-1]) << 6)

data.append((datavalue >> 16) & 0xFF)

data.append((datavalue >> 8) & 0xFF)

return dataclass Base64Error(Exception):

"""

Exception for Base64 error.

"""

pass

字符串转换def strbase64(astr):

"""

Convert a string to Base64 format string.

"""

return binbase64(map(ord, astr))def base64str(encodedstr):

"""

Convert Base64 format string to a string.

"""

return "".join(map(chr,base64bin(encodedstr)))

文件转换

文件转换要用到这里介绍的filehleper。另外,RFC

822规定,Base64文本没行76个字符,可存76/4*3=57个字节。所以我们每次读入57个字节处理。def binfiletobase64(inp, out):

"""

Convert binary file to Base64 format text file.

"""

blocksize = 76 / 4 * 3

def _binfiletobase64(fin, fout):

while True:

chunk = fin.read(blocksize)

if chunk:

fout.write(strbase64(chunk))

fout.write("\n")

else:

break

fileinoutpattern(inp, out, _binfiletobase64, inmode="rb", outmode="w")

def base64filetobin(inp, out):

"""

Convert Base64 format text file to binary file.

"""

def _base64filetobin(fin, fout):

for line in fin:

fout.write(base64str(line.rstrip()))

fileinoutpattern(inp, out, _base64filetobin, inmode="r", outmode="wb")

测试代码def test():

"""

Self testing.

"""

rawstr = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."

encodedstr = binbase64(map(ord, rawstr))

for x in range(0, len(encodedstr), 76):

print encodedstr[x:x+76]

encodedstr = strbase64(rawstr)

for x in range(0, len(encodedstr), 76):

print encodedstr[x:x+76]

data = base64bin(encodedstr)

decodedstr = "".join(map(chr,data))

print decodedstr

assert decodedstr == rawstr

decodedstr = base64str(encodedstr)

print decodedstr

assert decodedstr == rawstr

#base64str(encodedstr[:-1]);#Not multiple of 4

#base64str(encodedstr[:-3]+"==");#Too many '='

#base64str(encodedstr[:-2]+"()");#Invaild characters '(' and ')'

binfiletobase64(r"D:\2.zip", r"D:\2.txt")

base64filetobin(r"D:\2.txt", r"D:\2.1.zip")

print "OK"

if __name__ == "__main__":

test()

参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:1024 设计师:我叫白小胖 返回首页

打赏作者

weixin_39614831

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值