上一章节我们讨论了如何对txt文本文件进行读写操作,这一张将讨论如何进行二进制文件的写与读。《Python 学习笔记(3)对txt文件的读与写操作(上)》的链接如下
1、uint32数据转换为4个字节
首先看下如何将uint32转换为4个字节。
temp = [0] * 4
uintdata = 123456
for i in range(4):
temp[i] = hex((uintdata >> i * 8) & 0xff)
计算结果如下:
但是如果数据位浮点数这样就行不通了。
可以用struct来解决bytes和其他二进制数据类型的转换。
2、 struct模块
struct的作用:将字节串解读为打包的二进制数据。
该模块执行Python值和以Python字节对象表示的C结构体之间的转换。 这可以用于处理存储在文件中的二进制数据或来自其他来源的网络连接的二进制数据。 它使用格式字符串作为C结构布局的紧凑描述,以及与Python值的转换。
2.1、struct模块中的功能
|
函数
|
return
|
explain
|
|
pack(fmt,v1,v2…)
|
string
|
按照给定的格式(fmt),把数据转换成字符串(字节流),并将该字符串返回.
|
|
pack_into(fmt,buffer,offset,v1,v2…)
|
None
|
按照给定的格式(fmt),将数据转换成字符串(字节流),并将字节流写入以offset开始的buffer中.(buffer为可写的缓冲区,可用array模块)
|
|
unpack(fmt,v1,v2…..)
|
tuple
|
按照给定的格式(fmt)解析字节流,并返回解析结果
|
|
pack_from(fmt,buffer,offset)
|
tuple
|
按照给定的格式(fmt)解析以offset开始的缓冲区,并返回解析结果
|
|
calcsize(fmt)
|
size of fmt
|
计算给定的格式(fmt)占用多少字节的内存,注意对齐方式
|
2.2、格式化字符串
当打包或者解包的时,需要按照特定的方式来打包或者解包。该方式就是格式化字符串,它指定了数据类型,除此之外,还有用于控制字节顺序、大小和对齐方式的特殊字符。
2.2.1、字节顺序、大小与对齐方式
为了同c中的结构体交换数据,还要考虑c或c++编译器使用了字节对齐,通常是以4个字节为单位,故而struct根据本地机器字节顺序转换。可以用格式中的第一个字符来改变对齐方式。定义如下
|
Character
|
Byte order
(字节顺序大小)
|
Size
|
Alignment
(对齐)
|
|
@(默认)
|
本机(native)
|
本机(native)
|
本机(native),凑够4个字节
|
|
=
|
本机(native)
|
标准(standard)
|
None,按原字节数
|
|
<
|
小端(little-endian)
|
标准(standard)
|
None,按原字节数
|
|
>
|
大端(big-endian)
|
标准(standard)
|
None,按原字节数
|
|
!
|
network(= big-endian大端)
|
标准(standard)
|
None,按原字节数
|
2.2.2、格式符
|
Format
格式符
|
C Type
(C
语言类型)
|
Python type
(Python
语言类型)
|
Standard size
|
|
x
|
pad byte(填充字节)
|
no value
|
|
|
c
|
Char
|
bytes 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(大写的i)
|
unsigned int
|
integer
|
4
|
|
l(小写的L)
|
long
|
integer
|
4
|
|
L
|
unsigned long
|
integer
|
4
|
|
q
|
long long
|
integer
|
8
|
|
Q
|
unsigned long long
|
integer
|
8
|
|
n
|
ssize_t
|
integer
|
|
|
N
|
size_t
|
integer
|
|
|
e
|
(6)
|
float
|
2
|
|
f
|
float
|
float
|
4
|
|
d
|
double
|
float
|
8
|
|
s
|
char[]
|
bytes
|
|
|
p
|
char[]
|
bytes
|
|
|
P
|
void*
|
integer
|
|
2.3、例子
f_data1 = 123.4567
f_data1 = struct.pack('<f', f_data1)
u_data1 = struct.unpack('<I', f_data1)
f_data2 = -123.4567
f_data2 =
struct.pack('<f', f_data2)
u_data2 = struct.unpack('<I', f_data1)
3、二进制文件读写
3.1、二进制文件写
好了,这下我们学会了如何将浮点数或者整形数据转换为bytes了,我们现在就看如何将浮点数或者整型数据存到二进制文本中。废话不多说,上代码:
"""
二进制文件中的浮点数存储
"""
FileName = 'w2.txt'
fid = open(Folder + '/' + FileName, 'wb')
s2 = 123.4567
s3 = -123.4567
DataBytes = struct.pack('<f', s2)
for i in range(4):
fid.write(c_uint8(DataBytes[i]))
DataBytes = struct.pack('<f', s3)
for i in range(4):
fid.write(c_uint8(DataBytes[i]))
fid.close()
最后生成了txt文件,如下所示,将显示改成hex的方式。
3.2、二进制文件读取
这个时候我们并不能认为结果是对的,我们可以用matlab读取验证或者用Python自己读取再将bytes数据转换为float。
3.2.1、Matlab读取二进制文件
Matlab的代码如下所示:
close all
clear
clc
fid = fopen('w2.txt','r');
data1 = fread(fid,1,'float');
data2 = fread(fid,1,'float');
我们以float的方式读取,发现读取的结果为123.4567和-123.4567,和我们一开始的赋值一致,证明那个我们这么写是成功了的。
3.2.2、Python读取二进制文件
FileName = 'w2.txt'
fid = open(Folder + '/' + FileName, 'rb')
DataBytes1 = fid.read(4)
S4 = struct.unpack('<f', DataBytes1)
DataBytes1 = fid.read(4)
S5 = struct.unpack('<f', DataBytes1)
fid.close()
4、写在最后
好了,关于Python如何读写 文本文件、二进制文件、将字符串写到txt文件中与将float或者int数据写到txt文件的方法大概就写到这,后面如果还遇到啥就继续补充吧。
文中对应的代码链接: