菜鸟学堂 -【Python struct】

本来想用python socket传输文件,结果悲剧发生,那么你懂的


struct

由于没有c语言基础,而且E文..,看官方文档,这个部分看的很蛋疼,果断百度。

http://docs.python.org/py3k/library/struct.html

struct. pack ( fmtv1v2... )

Return a bytes object containing the values v1v2, ... packed according to the format string fmt. The arguments must match the values required by the format exactly.

    返回一个字节对象,包含了v1,v2等,通过fmt格式化后的数据。参数必须和fmt需要格式化的完全对应起来。 struct. unpack ( fmtbuffer )

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:   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'来表示换行。




  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值