Python存储与读写二进制文件

技术背景

一般情况下我们会选择使用明文形式来存储数据,如json、txt、csv等等。如果是需要压缩率较高的存储格式,还可以选择使用hdf5或者npz等格式。还有一种比较紧凑的数据存储格式,就是直接按照二进制格式存储。这种格式下,存储的数据之间没有间隔符,在没有压缩的情况下应该是体积最小的存储类型。

使用方法

在Python中,我们可以使用numpy.tofile()功能,直接将numpy数组类型存储到一个二进制文件中。读取的时候,虽然可以直接使用open(file_name, 'rb')来进行读取,但是为了适配大量IO的场景,这里我们使用内存映射mmap的形式来进行数据读取。

完整示例

如下是一个完整的示例代码,相关的功能直接用注释的形式在代码中标记:

import numpy as np
import mmap
import resource
# 获取页数据量大小(单位:字节)
PAGE_SIZE = resource.getpagesize()
# 定义单精度浮点数数据占用字节(单位:字节)
DATA_SIZE = 4
# 计算页存储数据数量(num_float32)
PAGE_FNUM = int(PAGE_SIZE/DATA_SIZE)
print ("The PAGE_SIZE is: {}".format(PAGE_SIZE))
print ("Corresponding float32 numbers should be: {}".format(PAGE_FNUM))
# 生成示例数据,使用PAGE_FNUM+4大小的数据量定义两页数据
tmp_arr = np.arange(PAGE_FNUM+4).astype(np.float32)
# 数据存储路径
tmp_file = '/tmp/tmp.dat'
# 将数组存储到二进制文件中
tmp_arr.tofile(tmp_file)
# 每次从二进制文件中读取4个数据
READ_NUM = 4
with open(tmp_file, 'rb') as file:# 第一页数据的内存映射mm = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ, offset=0)# 第一页数据的1、2、3、4位数据print (np.frombuffer(mm.read(DATA_SIZE*READ_NUM), dtype='<f4'))# 第一页数据的5、6、7、8位数据print (np.frombuffer(mm.read(DATA_SIZE*READ_NUM), dtype='<f4'))# 第二页数据的内存映射mm = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ, offset=PAGE_SIZE)# 第二页数据的1~4位数据print (np.frombuffer(mm.read(DATA_SIZE*READ_NUM), dtype='<f4'))# 第二页数据的5~8位数据print (np.frombuffer(mm.read(DATA_SIZE*READ_NUM), dtype='<f4'))# 关闭内存映射mm.close()
# 退出文件IO

该脚本的输出结果为:

The PAGE_SIZE is: 4096
Corresponding float32 numbers should be: 1024
[0. 1. 2. 3.]
[4. 5. 6. 7.]
[1024. 1025. 1026. 1027.]
[]

结果解析

我们打印的第一个数据是页大小,这里显示是4096个字节。而一个单精度浮点数占4个字节,所以一页存了1024个单精度浮点数,也就是第二个打印输出的结果。由于我们定义的numpy数组是一个从0开始的递增数组,因此第一页数据的前8位数字就是从0到7。而第二页的数据是1024~1027一共4个浮点数,占16个字节。所以我们在第二页第二次使用numpy.frombuffer()去读取数据的时候,得到的是一个空的数组。此外我们可以查看一下这个二进制文件的大小:

In [1]: import osIn [2]: os.path.getsize('/tmp/tmp.dat')
Out[2]: 4112

一共是4112个字节,刚好是4096+16个字节。

总结概要

本文介绍了一种在Python中将Numpy数组转存为一个紧凑的二进制格式的文件,及其使用内存映射的形式进行读取的方案。一个二进制的数据流,不仅可以更加方便页形式的内存映射,相比于传统的Numpy单精度浮点数数组还有一个可哈希的特性。总体来说是一个对于高性能计算十分友好的存储格式,在cudaSPONGE中作为一个分子动力学模拟轨迹输出的格式使用。

版权声明

本文首发链接为:https://www.cnblogs.com/dechinphy/p/dat.html

作者ID:DechinPhy

更多原著文章:https://www.cnblogs.com/dechinphy/

请博主喝咖啡:https://www.cnblogs.com/dechinphy/gallery/image/379634.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/794573.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IIS标识介绍

原文链接:https://blog.csdn.net/weixin_30607659/article/details/95294969 应用程序池的标识是运行应用程序池的工作进程所使用的服务帐户名称。默认情况下,应用程序池以 Network Service 用户帐户运行,该帐户拥有低级别的用户权限。您可以将应用程序池配置为以 Windows S…

element-ui和element-plus

element-ui适配于vue2,无法于vue3适配,如果使用vue2,则下载element-ui npm i element-ui -S element-ui组件网址:https://element.eleme.cn/#/zh-CN/component/installation 如果使用vue3,则下载element-plus npm i element-plus -S npm install -D unplugin-vue-componen…

SQL SERVER -- JSON处理

-- JSON 字符串转 行记录 Declare @JsonStr Nvarchar(Max)=[{"State":0,"Name":"语文","ReMark":"了解国学信息","RepDtl":[{"ID":1,"Age":11},{"ID":2,"Age":12},{&quo…

shell解析json

shell解析json以下是几种不同的方法来在shell中解析JSON:使用awk命令和正则表达式:json={"name":"John","age":30,"city":"New York"} key=age value=$(echo $json | awk -v k="$key" BEGIN{RS=","; …

点击切换数据

点击按钮切换echarts图标样式,使数据在柱状图和折线图之间切换点击按钮切换echarts图标样式: renderChart 函数来初始化 ECharts 图表,需要在 switchTable 函数中修改图表的 option 并重新设置给图表实例。 <template> <BasicModal @register="registerModal&…

河南省12123公安厅临牌打印如何下载打印控件

关于“12123河南省公安厅临牌打印如何下载打印控件怎么安装打印控件”的问题公安交通管理综合应用平台打印控件安装失败,河南省公安厅临牌打印如何下载打印控件,12123临牌系统怎么安装打印控件? 关于“12123河南省公安厅临牌打印如何下载打印控件怎么安装打印控件”的问…

CF2006D Iris and Adjacent Products

题意 https://codeforces.com/contest/2006/problem/D 分析 考虑如果没有修改怎么重排最优。先把最大值丢进序列,再把最小值丢进序列,再把次大值丢进序列,再把次小值压进去,以此类推。感性理解的话不难发现这是最优情况,具体证明可以考虑调整法(但我懒)。 令 \(b\) 为 \…

动画修改材质球的值,使用脚本获取不到?

Problem of accessing material property which is modified by animation - Unity Engine - Unity Discussions