使用处理二进制(pack和用法)
转载自:
这篇文章写的很好,所以无耻的转了。。
有的时候要运用处理二进制数据, 像是, 进行存取文件操作时。在这个时候, 能够借助某些模块来达成。能够用以处理c语言里的结构体。
模块中最重要的三个函数是pack(), (), ()
# 四号程序员
依据给定的格式(fmt), 将数据进行封装从而成为字符串(实际上跟类似于c结构体的字节流是一样的)。
pack(fmt, v1, v2, ...)
依据给定的格式(fmt), 对字节流进行解析, 进而送还解析而出的tuple。
(fmt, )
# 计算给定的格式(fmt)占用多少字节的内存
上述fmt中,支持的格式为:
pad byte
no value
char
of 1
char
(3)
char
(3)
_Bool
bool
(1)
short
(3)
short
(3)
int
(3)
int
(3)
long
(3)
long
(3)
long long
(2), (3)
long long
(2), (3)
float
float
(4)
float
(4)
char
char
void *
(5), (3)
注1.q和Q只在机器支持64位操作时有意思
注2.每个格式前可以有一个数字,表示个数
注3, s格式用以表示具备一定长度的字符串, 4s的意思是长度为4的字符串, 然而p所代表的是字符串。
注4.P用来转换一个指针,其长度和机器字长相关
注5.最后一个可以用来表示指针类型的,占4个字节
要与c里的结构体开展数据交换, 得考虑到有的c或者c++编译器采用了字节对齐, 一般是以4个字节作为单位的32位系统, 所以依据本地机器字节顺序进行转换, 能够借助格式里的第一个字符去改变对齐方式, 定义如下:
none
big-
none
(= big-)
none
使用方法是放在fmt的第一个位置,就像’@’
例子1:
结构体如下:
# 四号程序员
凭借.recv接收到了一个处于上面的结构体方面的数据, 此数据处于字符串s里, 时下需要将它解析出来, 能够运用()函数:
# 四号程序员
在上面的格式字符串里头!意味着我们得运用网络字节顺序进行解析, 由于我们的数据是从网络那儿接收而来的, 在网络上进行传送之际它呈现为网络字节顺序。后续的H表明是一个short的id, 4s表示长度为4字节的字符串, 2I表示存在两个int类型的数据。
在当前, 经由一个途径, 于id、tag以及count之中, 已然留存好了我们的信息, 这是已经达成的状态。
同样,也可以很方便的把本地数据再pack成格式:
# 四号程序员
pack函数将id、tag、, count依照指定格式转变为结构体, 该结构体被转换为ss, (ss此时已成一字符串,实际上类似仿若c结构体的字节流), 借助.send(ss)能够把此字符串进行发送出去。
例子2:
# 四号程序员
# 将a变为二进制
在这个时候, bytes成为了一类字符串, 这类具有按字节特性的字符串, 其以字节形式呈现的存储内容, 与a的二进制所存储的内容是一模一样的。
去实施相反的操作, 眼下存在着二进制数据bytes, 这实际上是字符串, 把它以相反的方式转化成的数据类型:
# 四号程序员
如果是由多个数据构成的,可以这样:
# 四号程序员
这时的那种bytes已然是二进制形态的数据了, 能够直接去写入文件, 比如说.write(bytes)。
然后,当我们需要时可以再读出来,bytes=.read()
再通过.()解码成变量:
# 四号程序员
这称作fmt, 是格式化字符串, 由数字跟字符组成, 5s意味着占5个字符的字符串, 2i表示2个整数等, 下面是能用的字符及类型, ctype表明能够与当中的类型逐一对应。
注意:二进制文件处理时会碰到的问题
我们使用处理二进制文件时,需要用如下方法:
# 四号程序员
那么和=open(,’r')的结果到底有何不同呢?
不同之处有两个地方:
首先, 当运用’r'之际, 一旦遭遇’0x1A’, 便会被视作文件终结, 此即EOF。而采用’rb’的话, 便不会存有这般问题。也就是说, 要是你来进行二进制写入,随后再用文本读取出, 要是其间设有’0X1A’, 那就仅仅会读取出文件的一部分。当使用’rb’之时, 会一直读取直至文件末尾。
其次, 针对于字符串x等于’abc\ndef’这种情况, 我们能够借助len(x)获取到它的长度是7, 我们把它称作换行符, 实际上它是’0X0A’。在采用’w'也就是文本方式去写时, 在平台上会自动地把’0X0A’转变为两个字符’0X0D’, ’0X0A’, 也就是说文件长度实际上变为8。当运用’r'文本方式来读取时, 又会自动地转换为原本的换行符。要是换成’wb’二进制方式来写的话, 就会使一个字符保持不变, 读取的时候同样是按照原样读取。因此要是采用文本方式进行写入, 而以二进制方式去读取, 那就得对这多出来的一个字节予以考量了。’0X0D’又被称作回车符。在linux环境下不会发生改变。原因在于linux仅仅运用’0X0A’来表示换行。