本来想用python socket传输文件,结果悲剧发生,那么你懂的
struct
由于没有c语言基础,而且E文..,看官方文档,这个部分看的很蛋疼,果断百度。
http://docs.python.org/py3k/library/struct.html
struct. pack ( fmt, v1, v2, ... )
Return a bytes object containing the values v1, v2, ... packed according to the format string fmt. The arguments must match the values required by the format exactly.
Unpack from the buffer buffer (presumably packed by pack(fmt, ...)) according to the format string fmt. The result is a tuple even if it contains exactly one item. The buffer must contain exactly the amount of data required by the format (len(bytes) must equal calcsize(fmt)).
pack的逆向操作,只有一个对象也返回tuple。
Return the size of the struct (and hence of the bytes object produced by pack(fmt, ...)) corresponding to the format string fmt.
根据fmt的格式,返回需要的字节大小
通俗解释:pack(fmt, v1, v2, ...) 按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流)
unpack(fmt, string) 按照给定的格式(fmt)解析字节流string,返回解析出来的tuple
calcsize(fmt) 计算给定的格式(fmt)占用多少字节的内存
'''
Created on 2012-4-12下午9:40:49
@author: yasenagat
@email: yasenagat@gmail.com
'''
#--看了看,方法很少,重点就两个pack,unpack,还有一个calcsize
#这个官方文档不好的地方,我感觉就是返回值太蛋疼,看半天E问才能看见,到底是什么类型的返回值,非常不直观。
#E文吃力的,直接飘过吧
from struct import *
#一、
#先说说要做什么吧
#我要把1这个数字,按照我自己定的规则打包,然后在解包
#规则
fmt = 'i'
#压缩包
a = pack(fmt,1)
print(a)# 压包后 b'\x01\x00\x00\x00'
#解压缩包
b = unpack(fmt,a)
print(b)# 解包后 (1,)
#用错误的规则解包,报错!!!
#b = unpack('s',a)
print(b)
#struct.error: unpack requires a bytes object of length 1
#需要一个长度为1的字节数组对象
#那么为什么是1呢?
length = calcsize('s')
print(length)
#原来错误的fmt需要的长度是1
#看看争取的需要长度是多少呢
print(calcsize(fmt))# 4,正确的需要长度是4
#二、
#压包多个数据
#是这样的,fmt这个是后写的,你只有只要要压缩的数据类型,才能知道你的fmt
a = pack('4s2sif2s',b'abcd',b'gg',1,23.98,b'hi')
print(a) # b'abcdgg\x00\x00\x01\x00\x00\x00\n\xd7\xbfAhi'
a = pack('1s2sif2s',b'abcd',b'gg',1,23.98,b'hi')
print(a) # b'agg\x00\x01\x00\x00\x00\n\xd7\xbfAhi'
a = pack('5s2sid2s',b'abcd',b'gg',1,23.98,b'hi')
print(a) # b'abcd\x00gg\x00\x01\x00\x00\x00\x00\x00\x00\x00{\x14\xaeG\xe1\xfa7@hi'
b = unpack('5s2sid2s',a)
print(b) # (b'abcd\x00', b'gg', 1, 23.98, b'hi')
#如果你能看懂,那么你很给力,反正我开始是没看懂
#看懂的略过,没看懂的往下看
#a = pack('4s2sif2s',b'abcd',b'gg',1,23.98,b'hi')#print(a) # b'abcdgg\x00\x00\x01\x00\x00\x00\n\xd7\xbfAhi'#pack(fmt,v1,v2...)#v1,v2支持的格式入下:
你找破头,发现都没找到字符串这个东西,那么呵呵,如果你想搞字符串,只能选择这个bytes了
所以,b'abcd',要加一个b。
('4s2sif2s',b'abcd',b'gg',1,23.98,b'hi'),
4s2sif2s是fmt,后面的都是value值,4s是4个s,s=bytes(见上面),所以4s对应的是b'abcd',如果你写成3s,那么,会少取一个,写成5s,自己看吧,试试,如果没写,那。。。。
i=integer对应1,
f=float对应23.98,用f有点小问题,应该用d。
这会你懂了吗?
fmt乱写会报错的呀
a = pack('3i',b'abcd',b'gg',1,23.98,b'hi')
你看看报错不!
3i是说有3个i,i是integer,就是有3个integer,明显是错的。
对的,请看下面:
a = pack('4s2sid2s',b'abcd',b'gg',1,23.98,b'hi')
#解压如下:
#一:
b = unpack('4s2sid2s',a)
print(b)
print(str(b[0],'utf-8'))
#二:
b1,b2,b3,b4,b5 = unpack('4s2sid2s',a)
print(str(b1,'utf-8'))
print(b4)
哪个更好点呢?
注意:二进制文件处理时会碰到的问题
我们使用处理二进制文件时,需要用如下方法
binfile=open(filepath,'rb') 读二进制文件
binfile=open(filepath,'wb') 写二进制文件
那么和binfile=open(filepath,'r')的结果到底有何不同呢?
不同之处有两个地方:
第一,使用'r'的时候如果碰到'0x1A',就会视为文件结束,这就是EOF。使用'rb'则不存在这个问题。即,如果你用二进制写入再用文本读出的话,如果其中存在'0X1A',就只会读出文件的一部分。使用'rb'的时候会一直读到文件末尾。
第二,对于字符串x='abc\ndef',我们可用len(x)得到它的长度为7,\n我们称之为换行符,实际上是'0X0A'。当我们用'w'即文本方式写的时候,在windows平台上会自动将'0X0A'变成两个字符'0X0D','0X0A',即文件长度实际上变成8.。当用'r'文本方式读取时,又自动的转换成原来的换行符。如果换成'wb'二进制方式来写的话,则会保持一个字符不变,读取时也是原样读取。所以如果用文本方式写入,用二进制方式读取的话,就要考虑这多出的一个字节了。'0X0D'又称回车符。linux下不会变。因为linux只使用'0X0A'来表示换行。