使用struct处理二进制
有的时候需要用python处理二进制数据,比如,存取文件、socket操作时。这时候,可以使用python的struct模块来完成。
struct模块中最重要的三个函数是pack(), unpack(), calcsize()
pack(fmt, v1, v2, ...) 按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流)
unpack(fmt, string) 按照给定的格式(fmt)解析字节流string,返回解析出来的tuple
calcsize(fmt) 计算给定的格式(fmt)占用多少字节的内存
struct中支持的格式如下表:
|
Format |
C Type |
Python |
字节数 |
|
x |
pad byte |
no value |
1 |
|
c |
char |
string of length 1 |
1 |
|
b |
signed char |
integer |
1 |
|
B |
unsigned char |
integer |
1 |
|
? |
_Bool |
bool |
1 |
|
h |
short |
integer |
2 |
|
H |
unsigned short |
integer |
2 |
|
i |
int |
integer |
4 |
|
I |
unsigned int |
integer or long |
4 |
|
l |
long |
integer |
4 |
|
L |
unsigned long |
long |
4 |
|
q |
long long |
long |
8 |
|
Q |
unsigned long long |
long |
8 |
|
f |
float |
float |
4 |
|
d |
double |
float |
8 |
|
s |
char[] |
string |
1 |
|
P |
void * |
long |
注1.q和Q只在机器支持64位操作时有意思
注2.每个格式前可以有一个数字,表示个数
注3.P用来转换一个指针,其长度和机器字长相关
为了同c中的结构体交换数据,还要考虑有的c或c++编译器使用了字节对齐,通常是以4个字节为单位的32位系统,故而struct根据本地机器字节顺序转换.可以用格式中的第一个字符来改变对齐方式.定义如下:
| Character | Byte | Size and alignment |
| @ | native | native 凑够4个字节 |
| = | native | standard 按原字节数 |
| < | little-endian | standard 按原字节数 |
| > | big-endian | standard 按原字节数 |
| ! | network(=big-endian) | standard 按原字节数 |
使用方法是放在fmt的第一个位置,就像'@5s6sif'
1、比如有一个结构体
struct Header
{
unsigned short id;
char[4] tag;
unsigned int version;
unsigned int count;
}
通过socket.recv接收到了一个上面的结构体数据,存在字符串s中,现在需要把它解析出来,可以使用unpack()函数。
import struct
id, tag, version, count = struct.unpack("!H4s2I", s)
就通过一个unpack,现在id, tag, version, count里已经保存好我们的信息了。同样,也可以很方便的把本地数据再pack成struct格式。
ss = struct.pack("!H4s2I", id, tag, version, count);
pack函数就把id, tag, version, count按照指定的格式转换成了结构体Header,ss现在是一个字符串(实际上是类似于c结构体的字节流),可以通过 socket.send(ss)把这个字符串发送出去。
2、二进制实例
import struct
a=12.34
bytes=struct.pack('i',a)
再进行反操作,现有二进制数据bytes,(其实就是字符串),将它反过来转换成python的数据类型:
a,=struct.unpack('i',bytes)
#a=12
注意,unpack返回的是tuple
如果是由多个数据构成的,可以这样:
a='hello'
b='world!'
c=2
d=45.123
bytes=struct.pack('5s6sif',a,b,c,d)
此时的bytes就是二进制形式的数据了,可以直接写入文件比如 binfile.write(bytes); 然后,当我们需要时可以再读出来,bytes=binfile.read();再通过struct.unpack()解码成python变量
a,b,c,d=struct.unpack('5s6sif',bytes)
注意:二进制文件处理时会碰到的问题
我们使用处理二进制文件时,需要用如下方法
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'来表示换行。
使用struct处理二进制的更多相关文章
- Pytho, struct处理二进制(pack和unpack)
[转]Python使用struct处理二进制(pack和unpack用法) Leave a reply 转载自:http://www.cnblogs.com/gala/archive/2011/09/ ...
- Python使用struct处理二进制
有的时候需要用python处理二进制数据,比如,存取文件,socket操作时.这时候,可以使用python的struct模块来完成.可以用 struct来处理c语言中的结构体. struct模块中最重 ...
- C++和python使用struct传输二进制数据结构来实现
网络编程问题往往涉及二进制数据的传输.在C++经常使用的传输是文本字符串和分组结构. 假设该数据可以预先送入连续的内存区域,然后让send函数来获得的第一个地址,这一块连续的内存区就能完成传输数据.文 ...
- Python使用struct处理二进制(pack和unpack用法)
转载自:http://www.cnblogs.com/gala/archive/2011/09/22/2184801.html 这篇文章写的很好,所以无耻的转了.. 有的时候需要用python处理二进 ...
- Python采用struct处理二进制
有时需要使用python二进制数据,实例,件.socket操作时.这时候.能够使用python的struct模块来完毕.能够用 struct来处理c语言中的结构体. struct模块中最重要的三个函数 ...
- struct:二进制数据结构的打包与解包
介绍 struct模块包括一些函数,这些函数可以完成字节串与原生Python数据类型(如数字和字符串)之间的转换 函数与Struct类 struct提供了一组处理结构值的模块级函数,另外还有一个Str ...
- 利用php unpack读取c struct的二进制数据,struct内存对齐引起的一些问题
c语言代码 #include <stdio.h> struct test{ int a; unsigned char b; int c; }; int main(){ FILE *fp; ...
- python音频处理用到的操作
作者:桂. 时间:2017-05-03 12:18:46 链接:http://www.cnblogs.com/xingshansi/p/6799994.html 前言 本文主要记录python下音频 ...
- Protocol Buffer 序列化原理大揭秘 - 为什么Protocol Buffer性能这么好?
前言 习惯用 Json.XML 数据存储格式的你们,相信大多都没听过Protocol Buffer Protocol Buffer 其实 是 Google出品的一种轻量 & 高效的结构化数据存 ...
随机推荐
- NPM (node package manager) 入门 - 基础使用
什么是npm ? npm 是 nodejs 的包管理和分发工具.它可以让 javascript 开发者能够更加轻松的共享代码和共用代码片段,并且通过 npm 管理你分享的代码也很方便快捷和简单. 截至 ...
- 【探索】在 JavaScript 中使用 C 程序
JavaScript 是个灵活的脚本语言,能方便的处理业务逻辑.当需要传输通信时,我们大多选择 JSON 或 XML 格式. 但在数据长度非常苛刻的情况下,文本协议的效率就非常低了,这时不得不使用二进 ...
- SignalR代理对象异常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的结论
异常汇总:http://www.cnblogs.com/dunitian/p/4523006.html#signalR 后台创建了一个DntHub的集线器 前台在调用的时候出现了问题(经检查是代理对象 ...
- xpath提取多个标签下的text
title: xpath提取多个标签下的text author: 青南 date: 2015-01-17 16:01:07 categories: [Python] tags: [xpath,Pyth ...
- 窥探Vue.js 2.0 - Virtual DOM到底是个什么鬼?
引言 你可能听说在Vue.js 2.0已经发布,并且在其中新添加如了一些新功能.其中一个功能就是"Virtual DOM". Virtual DOM是什么 在之前,React和Em ...
- # PHP - 使用PHPMailer发邮件
PHPMailer支持多种邮件发送方式,使用起来非常简单 1.下载PHPMailer https://github.com/PHPMailer/PHPMailer,下载完成加压后, 把下边的两个文件复 ...
- bzoj3207--Hash+主席树
题目大意: 给定一个n个数的序列和m个询问(n,m<=100000)和k,每个询问包含k+2个数字:l,r,b[1],b[2]...b[k],要求输出b[1]~b[k]在[l,r]中是否出现. ...
- IIS8 使用FastCGI配置PHP环境支持 过程详解
平时帮朋友们配置过一些PHP环境的服务器,但是一直使用的都是Apache HTTP+PHP,今天呢,我吧IIS+PHP配置方式给大家发一下下~呵呵. 在这里,我使用的是FastCGI模块映射的方式配置 ...
- NodeJS使用mysql
1.环境准备 手动添加数据库依赖: 在package.json的dependencies中新增, "mysql" : "latest", { "nam ...
- chattr用法
[root@localhost tmp]# umask 0022 一.chattr用法 1.创建空文件attrtest,然后删除,提示无法删除,因为有隐藏文件 [root@localhost tmp] ...