pythonstructpackstring_python与CC++中基本类型的相互转换
s。。。
使⽤struct.pack⼀定要注意是在64位系统还是32位系统。
如struct.pack('L', 1) 返回长度在64位系统 返回长度是8,32位系统 回返是4
以下⾃⼰写个转换算法
DWORD_LEN = 4 #为32位系统
CONST_SQRT = [256 ** i for i in range(DWORD_LEN)]
def _PyInt_to_CBinStr(nVal):
'''把py的int转 成C中的int,返回py的str,即C中int的⼆进制形式;
注:转换时,以低字节在前⾯,即intel CPU字节排序⽅式。'''
retBinStr = ''
for i in range(DWORD_LEN -1, -1, -1):
retBinStr =  '%c%s' % (chr(nVal / CONST_SQRT[i]),  retBinStr)
nVal %=  CONST_SQRT[i]
return retBinStr
def _CBinStr_Int_to_PyInt(str_CBin):
'''把C形式的⼆进制int转 成py的int。
注:转换时,以低字节在前⾯,即intel CPU字节排序⽅式。'''
nPyInt = 0
for i in range(DWORD_LEN):
nPyInt += ord(str_CBin[i]) * CONST_SQRT[i]
return nPyInt
今天遇到个⽤python 以⼆进制⽅式写⽂件的问题,想把 py中的 数值写进⽂件,如下:
f = open(r'c:/t.bin', 'wb')
f.writer(1) # 这⾥是不能直接转数值参数的,要作个转换成⼆进制buff
上⾯这个转,浪费偶超多时间查资料。。。。
t;p>最终py的内置库可以作转换 struct
import struct
strBuff = struct.pack('L'. 1)
f.write(strBuff)
关于 struct.pack 的第⼀个参数 fmt ---转换⽅式,内置⽂档中有说明,也害了很久。。。
对应表如下:
fmt参数:
Format
quot;>C Type
Python
Notes
x
pad byte
no value
c
char
string of length 1
b
signed char
integer
B
unsigned char
integer
h
short
integer
H
s="ctype">unsigned short integer
i
int
integer
I
unsigned int
long
l
long
integer
L
unsigned long
long
q
long long
c++中string的用法long
(1)
Q
unsigned long long
long
(1)
f
float
float
d
double
float
s
char[]
string
p
char[]
string
P
void *
integer
这两天做TCP协议,数据的传输都是⼆进制的,需要解释,于是⽤到了struct
看到这样⼀句代码:
length = struct.unpack('>I', self.buffer[:4])[0]
当时没有明⽩format=">I"是什么意思,从google了⼀下,有⼈说这个东西,可都是⽐较笼统,没能让我明⽩,于是硬着头⽪看API:
By default, C numbers are represented in the machine’s native format and byte order, and properly aligned by skipping pad bytes if necessary (according to the rules used by the C compiler).
通常,C语⾔下数字都是机器语⾔的格式并且按照字节排序,同时在需要的情况下会利⽤跳过填补的字节来进⾏适当的调整
Alternatively, the first character of the format string can be used to indicate the byte order, size and alignment of the packed data。
⾮此即彼:字符串的第⼀个字符要么被⽤于表⽰字符串的字节的排序,或者是字符串的size,还有就是数据是否对准。
Native byte order is big-endian or little-endian, depending on the host system. For example, Motorola and Sun processors are big-endian; Intel and DEC processors are little-endian.
计算机的字节序要么是⾼位顺序,要么是低位的,这依赖于主机本⾝。⽐如,摩托罗拉和sun的处理器是⾼位的,但是intel和DEC的是低位的。
这样⼦就明⽩了上⾯的format=">I"的意思,也就是说按照⾼位顺序来格式化取得⼀个int或long值。下⾯问题就⼜来了,你怎么知道读取的就是⼀个int或long值呢?
通过看struct的⽂档,可以看到struct通过两张表制定了⼀定的format规则,我按照⾃⼰的观察,给他归纳为两类,⼀个是和C当中类型的对照,另⼀个就是选择按照⾼位还是低位来解释字节。上⾯已经说了⾼低字节顺序,那么观察和C对照的表格,发现I 代表的就是integer or long ,详细的可以去看python的API。
下⾯是⼀些使⽤的例⼦,具体的使⽤,可以参考这些例⼦:
# 取前5个字符,跳过4个字符华,再取3个字符
format = '5s 4x 3s'
2. 使⽤struck.unpack获取⼦字符串
import struct
print struct.unpack(format, 'Test astring')
#('Test', 'ing')
来个简单的例⼦吧,有⼀个字符串'He is not very happy',处理⼀下,把中间的not去掉,然后再输出。
import struct
theString = 'He is not very happy'
format = '2s 1x 2s 5x 4s 1x 5s'
print ' '.join(struct.unpack(format, theString))
输出结果:
He is very happy
随后是关于⽹络字节的东东,从⽹上看来的,感觉有⽤:
Python的socket库采⽤string类型来发送和接收数据,这样当我们⽤
i = v(4)
来接收⼀个4字节的整数时,该整数实际上是以⼆进制的形式保存在字符串 i 的前4个字节中;⼤多数的时候我们需要的是⼀个真正的integer/long型,⽽不是⼀个⽤string型表⽰的整型。这时我们可以使⽤struct库:Interpret
strings as packed binary data. 对上⾯的情况,我们可以写 t = unpack("I", i) 第⼀个参数是格式化字符串,I指明字符串 i 包含的头⼀个数据项是⼀个以C语⾔的unsigned integer表⽰的整数,这⾥ i 只包含了⼀个数据项,实际上这个被解释的字符串也可以包含多个数据项,只要在格式化字符串⾥为每项数据指明⼀个格式即可;⾃然地,unpack返回的就是⼀个tuple类型了。