本来想用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.
返回一个字节对象,包含了v1,v2等,通过fmt格式化后的数据。参数必须和fmt需要格式化的完全对应起来。 struct. unpack ( fmt, buffer ) ¶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。
struct. calcsize ( fmt )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: [email protected]
'''
#--看了看,方法很少,重点就两个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'来表示换行。