首页 > 其他分享 >复杂二进制数据

复杂二进制数据

时间:2024-04-27 14:33:37浏览次数:16  
标签:小端 struct format 二进制 double self 复杂 flattened 数据

点击查看代码
# 读取嵌套型和大小可变的二进制结构
from itertools import chain
import struct

# 多边形数组
polys = [
    [(1.0, 2.1), (2.0, 3.2), (3.0, 4.3)],
    [(1.1, 2.2), (2.1, 3.3), (3.1, 4.4), (4.1, 5.5)],
    [(1.2, 2.3), (2.2, 3.4), (3.1, 4.5)],
]

# 文件格式
"""
文件头
    字节        类型                描述
    0          int               文件代码(0x1234, 小端)
    4          double            x的最小值(小端)
    12         double            y的最小值(小端)
    20         double            x的最大值(小端)
    28         double            y的最大值(小端)
    36         int               多边形数量
正文
    字节        类型                描述
    0          int               记录长度(N字节)
    4-N        Points            (X,Y)坐标,以浮点数表示
"""


def write_ploys(filename, polys):
    flattened = list(chain(*polys))
    min_x = min(x for x, y in flattened)
    min_y = min(y for x, y in flattened)
    max_x = max(x for x, y in flattened)
    max_x = max(x for x, y in flattened)
    with open(filename, "wb") as f:
        head = struct.pack("<iddddi", 0x1234, min_x, min_y, max_x, max_x, len(polys))
        f.write(head)

        for ploy in polys:
            size = len(ploy) * struct.calcsize("<dd")
            f.write(struct.pack("<i", size + 4))
            for pt in ploy:
                f.write(struct.pack("<dd", *pt))


write_ploys("binary_complex", polys)


def read_polys(filename):
    with open(filename, "rb") as f:
        head = f.read(40)
        file_code, min_x, min_y, max_x, max_y, num_polys = struct.unpack(
            "<iddddi", head
        )
        print(
            "read file head: ", file_code, min_x, min_y, max_x, max_y, num_polys
        )  # read file head:  4660 1.0 2.1 4.1 4.1 3

        polys = []
        for i in range(num_polys):
            poly = []
            (pbytes,) = struct.unpack("<i", f.read(4))
            for j in range(pbytes // 16):
                poly.append(struct.unpack("<dd", f.read(16)))
            polys.append(poly)

        print(
            "read polys: ", polys
        )  # read polys:  [[(1.0, 2.1), (2.0, 3.2), (3.0, 4.3)],
        # [(1.1, 2.2), (2.1, 3.3), (3.1, 4.4), (4.1, 5.5)],
        # [(1.2, 2.3), (2.2, 3.4), (3.1, 4.5)]]


read_polys("binary_complex")


# 上面的代码比较乱 对上面代码的优化
print("-" * 10)


class StructField:
    """Descriptor representing a simple struct field"""

    def __init__(self, format, offset):
        self.format = format
        self.offset = offset

    def __get__(self, instance, cls):
        if instance is None:
            return self
        r = struct.unpack_from(self.format, instance._buffer, self.offset)
        return r[0] if len(r) == 1 else r


class Structure:
    def __init__(self, bytedata):
        self._buffer = memoryview(bytedata)


class PolyHead(Structure):
    file_code = StructField("<i", 0)
    min_x = StructField("<d", 4)
    min_y = StructField("<d", 12)
    max_x = StructField("<d", 20)
    max_y = StructField("<d", 28)
    num_polys = StructField("<i", 36)


with open("binary_complex", "rb") as f:
    phead = PolyHead(f.read())
    print("phead hex file_code: ", hex(phead.file_code))
    print("phead min_x: ", phead.min_x)
    print("phead num_polys", phead.num_polys)

print("-" * 10)


# 上边这么写很有趣, 但这种方法还有问题,代码比较冗长,重复使用StructField, 要指定偏移量等
# 任何时候,面对冗长的类定义的时候,应考虑用类装饰器或者元类进行优化
class StructureMeta(type):
    """Metaclass that automatically creates StructFiled descriptors"""

    def __init__(self, clsname, bases, clsdict):
        fields = getattr(self, "_fields_", [])
        byte_order = ""
        offset = 0
        for format, fieldname in fields:
            if format.startswith(("<", ">", "!", "@")):
                byte_order = format[0]
                format = format[1:]
            format = byte_order + format
            setattr(self, fieldname, StructField(format, offset))
            offset += struct.calcsize(format)
        setattr(self, "struct_size", offset)


class StructurePro(metaclass=StructureMeta):
    def __init__(self, bytedata):
        self._buffer = bytedata

    @classmethod
    def from_file(cls, f):
        return cls(f.read(cls.struct_size))


class PolyHeaderPro(StructurePro):
    _fields_ = [
        ("<i", "file_code"),
        ("d", "min_x"),
        ("d", "min_y"),
        ("d", "max_x"),
        ("d", "max_y"),
        ("i", "num_polys"),
    ]


with open("binary_complex", "rb") as f:
    phead_pro = PolyHeaderPro.from_file(f)
    # phead_pro = PolyHeaderPro(f.read())
    print("phead_pro hex file_code: ", hex(phead_pro.file_code))
    print("phead_pro min_x: ", phead_pro.min_x)
    print("phead_pro num_polys", phead_pro.num_polys)

标签:小端,struct,format,二进制,double,self,复杂,flattened,数据
From: https://www.cnblogs.com/yimeimanong/p/18162018

相关文章

  • ICESat-2 ATL03光子数据读取
    ICESat-2数据处理的方式一般为将光子数据投影到沿轨距离和高程的二维空间。如下图:ATL03数据读取H5是一种数据存储结构,读取原理就是按照该结构获取数据,这里给出两种读取方式。ATL03的数据字典:ATL03ProductDataDictionary(nsidc.org)使用pandasimportwarningsimportpan......
  • 一键启动的AI离线知识库,无需复杂环境依赖,小白都能上手了
    简介在人工智能技术飞速发展的今天,我们经常面临一个挑战:如何快速、简便地部署和使用AI技术?AntSK项目,一个开源的AI知识库和智能体,就是为了解决这一问题而诞生的。现在,我们自豪地宣布,AntSK已经实现了无需复杂部署的一键启动功能,让每个人都能轻松拥抱AI的便利。为什么选择AntSK?......
  • 使用restful请求华三模拟器上的设备接口数据
    一、resful介绍RESTful采用C/S模型。RESTful客户端为使用Python、Ruby或Java等编程语言开发出的RESTful客户端程序或脚本。RESTful服务器为网络设备。通过RESTful功能配置和维护设备的过程为:(1)客户端向服务器发送HTTP/HTTPS请求报文,通过HTTP的方法来操作指定的RESTfulAPI......
  • 微服务想缓存一些数据,不希望重复调用。java SoftReference软引用存储缓存
    背景:微服务我们要调用字典数据,但是很多都是要重复调用的,没有缓存,我为了设置一个应用的缓存,并且可以定时清理,更新 首先定义两个静态数据,。一个软连接缓存,一个定时清理线程privatestaticSoftReference<Map<String,Map<String,DictionaryVo>>>plmDicMapCache=newSoftR......
  • 从海量数据表中筛选符合不同条件组合的数据的SQL优化
    速度很慢的SQL脚本SETNOCOUNTON;DECLARE@snVARCHAR(200);DECLARE@nINT;DECLARE@sn_tabTABLE(idBIGINT,snVARCHAR(200));IFOBJECT_ID('tempdb..#tab_f1')ISNOTNULLDROPTABLE#tab_f1CREATETABLE#tab_f1(idBIGINT)CREATEINDEXidx_f1_id......
  • 有没有大佬知道这种数据应该怎么抓取呀?
    大家好,我是Python进阶者。一、前言前几天在Python白银交流群【王者级混子】问了一个Python网络爬虫的问题。问题如下:有没有大佬知道这种数据应该怎么抓取呀?我鼠标移到上面才会出现的数据。二、实现过程这里【Crazy】和【此类生物】给了一个指导。后来粉丝也查了下谷歌,好像......
  • access数据库批量更新中无法使用replace,出现“表达式中 'replace' 函数未定义”的替代
    如果我们想要批量修改数据库table_name表中aa字段中数据,将“|bbbb”删除sql的批量更新中,通用语法是:UPDATEtable_nameSETaa=REPLACE(aa,'|bbbb','')但是,如果是access数据库,就可能出现以下的报错信息:MicrosoftJETDatabaseEngine错误'80040e14'表达式中'replace'函......
  • 37.Android数据存储再整理
    这次主要是对SD卡外部存储和SharedPreferences存储的补充说明还是以qq案例来说首先外部存储存储的位置为/storage/emulated/0目录下具体为你定义的地方这里也有个小坑还有就是不需要使用内部存储的openFileOutput方法和openFileInput方法首先要在清单文件里申请SD卡写读......
  • 陈畅亮搞的专利在Windows上利用加解密DLL模块对数据库连接字符串进行加解密
    陈畅亮搞的专利在Windows上利用加解密DLL模块对数据库连接字符串进行加解密  这种专利权人是公司,个人是发明人,专利年费是申请人先垫付,然后公司报销了,这个专利本身就不属于员工的这个是公司是专利权人, 使用权是公司,如果想要维持权利的话,需要缴纳年费,专利发明现在一个市......
  • 在数据库的查询与更新中,CHARINDEX与instr的区别?
    在数据库和字符串处理的领域中,CHARINDEX和INSTR是两个常用的函数,它们都用于查找子字符串在主字符串中的位置。尽管这两个函数在功能上有所重叠,但它们之间存在一些关键的区别,这些区别可能会影响开发者在选择使用哪一个函数时的决策。首先,CHARINDEX是SQLServer中的一个内置函数,它......