Python工具箱系列(三十七)

news2024/12/29 9:38:48

二进制文件操作(上)

python比较擅长与文本相关的操作。但现实世界中,对于非文本消息的处理也很普遍。例如:

◆通过有线、无线传递传感器获得的测量数据。

◆卫星通过电磁波发送测量数据。

◆数据中心的数万台服务器发送当前CPU的占用率信息、内存占用量等众多指标数据。

以上数据,当然可以以文本方式发送,但是对于带宽的占用惊人。假设某个对于PM2.5进行测量的传感器,每隔一秒发送一次测量数据,以文本方式发送消息,内容如下:

"counter: 1, pm25: 170.24119426834042, timestamp: 2022-07-24 08:52:11.138894+00:00"

以上消息占用了81个字节。而如果能够按照约定的格式直接发送二进制数据,则只需要20个字节,可以大幅提升传输效率。此外,以文本方式在本地保存传感器数据,则一天就需要81*86400/1024=6834M字节,对于传感器这种体积小巧的嵌入式系统,存储空间极为有限,很快就会空间耗尽。因此,对非文本数据直接保存与读取非常有必要。下面的代码演示了传感器类,以及传感器测量数据的二进制文件存储与读取的基本操作。

import binascii
import random
import struct
from datetime import datetime
from io import BytesIO
from time import sleep

import arrow


class sensordata_v1():
    def __init__(self):
        utc = arrow.utcnow()
        self._timestamp = utc.to('Asia/Shanghai')

    @property
    def counter(self) -> int:
        """
        计数器

        Returns:
            int: 从0开始的计数器
        """
        return self._counter

    @counter.setter
    def counter(self, value: int):
        self._counter = value

    @property
    def pm25(self) -> float:
        """
        PM25测量值

        Returns:
            float: pm25的当前测量值
        """
        return self._pm25

    @pm25.setter
    def pm25(self, value: float):
        self._pm25 = value

    @property
    def timestamp(self) -> datetime:
        """
        当前时点

        Returns:
            datetime: 当前的时间
        """
        return self._timestamp.datetime

    def __str__(self):
        """
        以文字输出相关内容

        Returns:
            string: 说明性文字
        """
        return f"counter: {self.counter}, pm25: {self.pm25}, timestamp: {self.timestamp}"

    def __repr__(self):
        """
        输出字节流的16进制内容

        Returns:
            string: 16进制显示相关数值
        """
        return str(binascii.hexlify(self.toBytes()))

    def toBytes(self):
        """
        将相关数据转换成为bytes,便于网络传输或者写入文件

        Returns:
            bytes: 整合测量数据到字节流中
        """
        with BytesIO() as byio:
            byio.write(struct.pack('<i', self.counter))
            byio.write(struct.pack('<d', self.pm25))
            byio.write(struct.pack('<d', self._timestamp.timestamp()))
            return byio.getvalue()

    def fromBytes(self, data):
        """
        从字节流中解出相关值

        Args:
            data (bytes): 待解析的字节流
        """
        self.counter, self.pm25, st = struct.unpack('<idd', data)
        self._timestamp = arrow.get(st)


def toFile(filename):
    """
    向二进制文件中写入数据

    Args:
        filename (string): 文件名称
    """
    with open(filename, 'wb') as myfile:
        for index in range(10):
            sensor_obj = sensordata_v1()
            sensor_obj.counter = index
            sensor_obj.pm25 = random.uniform(0, 300)
            data = sensor_obj.toBytes()
            myfile.write(data)
            sleep(1)


def fromFile(filename):
    """
    从二进制文件中获得保存的信息,并且重建对象

    Args:
        filename (string): 文件名称
    """
    with open(filename, 'rb') as myfile:
        fmt = struct.Struct('<idd')
        datalen = fmt.size
        for index in range(10):
            data = myfile.read(datalen)
            sensor_obj = sensordata_v1()
            sensor_obj.fromBytes(data)
            print(sensor_obj)

datafilename = r"d:\dev\sensor.dat"
toFile(datafilename)
fromFile(datafilename)

其中arrow是非常值得推荐的时间处理框架。python有内置的时间处理框架,功能非常完善,但失之于乱与杂,掌握起来非常不易。而arrow则非常人性化,做到了拿来即用。其安装过程非常简单,直接pip install arrow即可。在示例程序中,为了能够方便存储,我们将时间戳直接用UNIX的timestamp来表示,转换后为了保持精度,本例使用double(8字节)存储,如果要求不高,可以改为float(4字节)。

sensordata_v1类使用@property装饰器来定义属性。总共有3个属性:

◆counter-计数器。从0开始计数累加,后续保存到数据库中时也方便检索。

◆pm25-PM2.5测量值。在示例代码中使用random.uniform模拟一个0到300的随机浮点值,没有什么太大的意义,保证每次不同即可。

◆timestamp-数据采集时的对应时间。

str类函数

可以自定义,本例中用它来直观的表示当前的采集值。当对sensordata_v1类的实例打印时,就会自动调用这个函数。

repr类函数

可以自定义,本例中用它来演示转换成为字节流bytes时的16进制值。对于程序员来说,16进制来表示字节是比较自然的。

toBytes类函数具体展示了如何将类的属性值转换成为二进制字节流,主要依靠python内置的struct模块。在内存中模拟文件打开一个BytesIO,并且依次写入struct.pack编码后的字节流,最终统一输出。

fromBytes类函数具体展示了如何从字节流反解成为对象的属性值。struct.pack与struct.unpack成对出现。

toFile函数将编码好的字节流写入二进制文件。写入的模式为'wb',其中w代表全覆盖写入的意思,b代表二进制模式的意思。fromFile负责从二进制文件读回保存的字节流,重新生成各个sensordata_v1对象。

生成的二进制文件,可以使用UltraEditor、InHex等。也可以直接使用vscode自带的2进制文件浏览器扩展Hex Editor,显示效果如下图所示:

 从图中可以看出,二进制文件确实节省空间,但人类不容易理解,必然借助于专用工具与代码来管理。但即使计算机与网络能力强悍如斯,二进制文件与网络上的字节流仍然必不可少,不可替代。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android Studio 配置 DCL 单例脚本

DCL&#xff08;Double-Checked Locking&#xff09;单例是一种用于创建单例对象的设计模式。单例模式是一种创建型模式&#xff0c;用于确保一个类只有一个实例&#xff0c;并提供全局访问点。 DCL单例的核心思想是使用双重检查来保证只有在需要时才对实例进行实例化。它结合…

MIT 6.830 数据库系统 -- Lab One

MIT 6.830 Lab One 项目拉取SimpleDB存储结构一览SimpleDB特性说明Lab One练习一练习二练习三练习四练习五练习六练习七 项目拉取 原项目使用ant进行项目构建&#xff0c;我已经更改为Maven构建&#xff0c;大家直接拉取我改好后的项目即可: https://gitee.com/DaHuYuXiXi/si…

物联网助力鲜花冷链安全——温湿度监控系统

近几年来我国花卉生产的发展尤为迅速&#xff0c;生产面积逐年扩大&#xff0c;产值成倍增长&#xff0c;内销市场越来越旺&#xff0c;出口创汇也有较大幅度上升。 随着人民生活水平的提高和可支配收入的增加&#xff0c;人们对鲜花的需求日益增长&#xff0c;花卉市场的前景…

电子药盒语音芯片ic解决方案WT588F02B-8S,免屏实现精准较时设定

概述&#xff1a;电子药盒是一种具备定时语音提醒服药的贴心智能家居用品&#xff0c;每天的服药时间是预先设定好的&#xff0c;到了设定的时间提醒声音就会响起&#xff0c;服药者因此就可以准时服药。许多需要每天服药的人士&#xff0c;尤其是老年人群体&#xff0c;经常会…

Matlab论文插图绘制模板第105期—带缺口的分组填充箱线图

在之前的文章中&#xff0c;分享了Matlab带缺口的分组箱线图的绘制模板&#xff1a; 进一步&#xff0c;再来分享一下带缺口的分组填充箱线图的绘制模板。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;加群的朋友请自…

算法leetcode|59. 螺旋矩阵 II(rust重拳出击)

文章目录 59. 螺旋矩阵 II&#xff1a;样例 1&#xff1a;样例 2&#xff1a;提示&#xff1a; 分析&#xff1a;题解&#xff1a;rust&#xff1a;go&#xff1a;c&#xff1a;python&#xff1a;java&#xff1a; 59. 螺旋矩阵 II&#xff1a; 给你一个正整数 n &#xff0c…

高速PCB设计中串行/并行信号的仿真与设计技巧

在高速PCB设计中&#xff0c;串行和并行信号的仿真是为了确保信号传输的准确性和完整性&#xff0c;随着系统数据传输速度的提高&#xff0c;准确模拟和优化信号的传输性能对于系统稳定性至关重要&#xff0c;那么你知道在高速PCB设计中&#xff0c;如何针对串行信号和并行信号…

jmeter夸线程组变量引用

通过BeanShell 后置处理程序引用函数&#xff1a; ${__setProperty(newvar,${oldvar},)}如下&#xff1a; 说明&#xff1a;HTTP_1返回结果msg的值为{“code”:200&#xff0c;“msg”:“操作成功”} 1.通过JSON提取器获取到要跨线程组的参数值 2.BeanShell后置处理程序引用…

杂谈:人到中年总得有点兴趣爱好

写在最前面&#xff1a; 前面一段写的是我咋喜欢的铜钱&#xff0c;后面一段是我对学习和转化的一点儿见解&#xff0c;有兴趣可以看看&#xff0c;甚至可以跳过前面去看看后面的内容~ 前几天跟朋友吃饭聊天&#xff0c;不知不觉中大家都到了中年&#xff0c;也都有点儿兴趣爱好…

SAP从入门到放弃系列之工艺路线-物料分配与组件分配-part1

文章概览 一、概述&#xff1a;二、基本概念&#xff1a;2.1、物料分配概览2.1.1物料适用场景&#xff1a;2.1.2物料分配方式&#xff1a; 2.2、组件分配概览2.2.1 组件适用场景2.2.2 组件分配注意事项&#xff1a; 三、测试示例3.1、准备工艺路线组数据&#xff1a;3.2、工艺路…

【Java】数组中的拷贝方法与初步理解深浅拷贝

文章目录 普通的数组拷贝函数可以指定区间拷贝的数组拷贝函数深浅拷贝 普通的数组拷贝函数 Arrays.copyOf(array,array.length) 我们进入到这个函数的源码中&#xff0c;可以看到这两个参数一个是原始数组&#xff0c;一个是拷贝后的新的长度。 例如&#xff1a; public cla…

YOLOv5图像和视频对象生成边界框的目标检测实践(GPU版本PyTorch错误处理)

识别图像和视频里面的对象&#xff0c;在计算机视觉中是一个很重要的应用&#xff0c;比如无人驾驶&#xff0c;这个就需要实时的检测到周边环境的各种对象&#xff0c;并及时做出处理。目标检测在以往的文章中有重点讲解过几种&#xff0c;其中Faster R-CNN的源码解读&#xf…

数据结构之复杂度分析

1、大 O 复杂度表示法 算法的执行效率&#xff0c;粗略地讲&#xff0c;就是算法代码执行的时间 这里有段非常简单的代码&#xff0c;求 1,2,3…n 的累加和。看如何来估算一下这段代码的执行时间 int cal(int n) {int sum 0;int i 1;for (; i < n; i) {sum sum i;}ret…

Vue3版本生命周期详解

介绍 vue3和vue2的生命周期改动不大,下面以图来展现两个版本的周期钩子 使用示例 配置项写法 vue3可以使用vue2版本的周期配置 准备一个HelloWord组件 使用App组件嵌套HelloWorld组件,并进行v-if判断是否卸载该组件,以此查看vue3的卸载钩子 测试: 可以看到当页面刷新后执行…

Maven的安装与使用

一、简介 1.什么是Maven? Maven翻译为“专家“&#xff0c; ”内行”的意思&#xff0c;是著名Apache公司下基于Java开发的开源项目。Maven项目对象模型&#xff08;POM&#xff09;是一个项目管理工具软件&#xff0c;可以通过简短的中央信息描述来管理项目的搭建&#x…

前端Vue自定义滚动卡片,可以用于商品海报生成

前端Vue自定义滚动卡片&#xff0c;可以用于商品海报生成&#xff0c; 下载完整代码请访问uni-app插件市场地址&#xff1a;https://ext.dcloud.net.cn/plugin?id13189 实现代码如下&#xff1a; # cc-scroolCard #### 使用方法 使用方法 <!-- dataInfo&#xff1a;滚动…

(1)ADS-B接收机

文章目录 前言 1.1 所需硬件 1.2 连接到自动驾驶仪 1.3 设置 1.4 ADSB输出配置 1.5 启用载人飞行器避障功能 1.6 飞行器数据库 1.7 开发者信息包括模拟 前言 本文介绍了如何安装和配置 ADS-B 模块&#xff0c;以便你的飞机能够知道附近的其他飞机和空中交通管制&#…

高性能消息中间件 RabbitMQ

一、RabbitMQ概念 1.1 MQ是什么 消息队列 MQ全称Message Queue&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保存消息的容器。多用于系统之间的异步通信。 同步通信相当于两个人当面对话&#xff0c;你一言我一语。必须及时回复&#xff1a; 异步通信相…

用API Key保护Spring Boot 接口的安全

1、概述 安全性在REST API开发中扮演着重要的角色。一个不安全的REST API可以直接访问到后台系统中的敏感数据。因此&#xff0c;企业组织需要关注API安全性。 Spring Security 提供了各种机制来保护我们的 REST API。其中之一是 API 密钥。API 密钥是客户端在调用 API 调用时提…

DAY 79 云原生DOCKER的基本原理及镜像管理

Docker概述 云计算涌现出很多改变传统IT架构和运维方式的新技术&#xff0c;比如虚拟机、容器、微服务、Serverless&#xff08;无服务&#xff09;&#xff0c;无论这些技术应用在哪些场景&#xff0c;降低成本、提升效率是云服务永恒的主题。 1.运行物理机&#xff0c;也称…