上一章节我们讨论了如何对txt文本文件进行读写操作,这一张将讨论如何进行二进制文件的写与读。《Python 学习笔记(3)对txt文件的读与写操作(上)》的链接如下​

1、uint32数据转换为4个字节

首先看下如何将uint32转换为4个字节。

# 计算一个无符号32位数据的bytes表达
temp = [0] * 4
uintdata = 123456
for i in range(4):
temp[i] = hex((uintdata >> i * 8) & 0xff)

计算结果如下:

Python 学习笔记(3)对txt文件的读与写操作(下)_文件输入输出

但是如果数据位浮点数这样就行不通了。

可以用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)

Python 学习笔记(3)对txt文件的读与写操作(下)_字符串_02

3、二进制文件读写

3.1、二进制文件写

好了,这下我们学会了如何将浮点数或者整形数据转换为bytes了,我们现在就看如何将浮点数或者整型数据存到二进制文本中。废话不多说,上代码:

"""
二进制文件中的浮点数存储
"""
FileName = 'w2.txt'
# 以二进制的形式打开一个指定文件夹,如果没有就创建,如果有就将原来的内容覆盖
fid = open(Folder + '/' + FileName, 'wb')
s2 = 123.4567
s3 = -123.4567
# 使用pack函数,将f数据 以小子端的方式转换为bytes
DataBytes = struct.pack('<f', s2)
for i in range(4):
fid.write(c_uint8(DataBytes[i])) # 在write的时候还是转换和成c_uint8,不然会报错
DataBytes = struct.pack('<f', s3)
for i in range(4):
fid.write(c_uint8(DataBytes[i]))
fid.close()

最后生成了txt文件,如下所示,将显示改成hex的方式。

Python 学习笔记(3)对txt文件的读与写操作(下)_文件输入输出_03

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');

Python 学习笔记(3)对txt文件的读与写操作(下)_python_04

我们以float的方式读取,发现读取的结果为123.4567和-123.4567,和我们一开始的赋值一致,证明那个我们这么写是成功了的。

3.2.2、Python读取二进制文件

    FileName = 'w2.txt'
# 以二进制的形式打开一个指定文件夹,如果没有就创建,如果有就将原来的内容覆盖
fid = open(Folder + '/' + FileName, 'rb')
DataBytes1 = fid.read(4) # 这边读出来是 bytes
# 将bytes解包为指定的数据类型
S4 = struct.unpack('<f', DataBytes1)
DataBytes1 = fid.read(4) # 这边读出来是 bytes
# 将bytes解包为指定的数据类型
S5 = struct.unpack('<f', DataBytes1)
fid.close()

Python 学习笔记(3)对txt文件的读与写操作(下)_python_05

4、写在最后

好了,关于Python如何读写 文本文件、二进制文件、将字符串写到txt文件中与将float或者int数据写到txt文件的方法大概就写到这,后面如果还遇到啥就继续补充吧。

文中对应的代码链接: