复杂二进制数据

点击查看代码
# 读取嵌套型和大小可变的二进制结构
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)

本文作者:一枚码农

本文链接:https://www.cnblogs.com/yimeimanong/p/18162018

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   一枚码农  阅读(9)  评论(0编辑  收藏  举报
 
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 Sold Out Hawk
  2. 2 光辉岁月 Beyond
Sold Out - Hawk
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : Jon Steingard

作曲 : Jon Steingard

I ain't like no one you met before

I'm running for the front

When they're all running for the door

And I won't sit down won't back out

You can't ever shut me up

Cause I'm on a mission

And I won't quit now

In a world full of followers

I'll be a leader

In a world full of doubters

I'll be a believer

I'm stepping out without a hesitation

Because the battle's already been won

I'm sold out

I'm no longer living

Just for myself

Running after Jesus

With my whole heart

And now I'm ready to show

I am sold out

I'm sold out

With every single

Step that I take now

With every drop of blood

Left in my veins

I'm gonna be making it count

I am sold out

This ain't just some temporary phase

You can't face this kind of grace

And leave the way you came

This is permanent with intent

And there won't be no stopping it now

I'm on a mission and it's heaven sent

In a world full of followers

I'll be a leader

In a world full of doubters

I'll be a believer

I'm stepping out without a hesitation

Cause my soul is like a stadium

I'm sold out

I'm no longer living

Just for myself

Running after Jesus

With my whole heart

And now I'm ready to shout

I am sold out

I'm sold out

With every single

Step that I take now

With every drop of blood

Left in my veins

I'm gonna be making it count

I am sold out

No trials coming against me

Could put a dent in my passion

They're just an opportunity

To put my faith into action

In a world full of followers

I'll be a leader

In a world full of doubters

I'll be a believer

I'm stepping out without a hesitation

I ain't got nothing left to be afraid of

I'm sold out

I'm no longer living

Just for myself

Running after Jesus

With my whole heart

And now I'm ready to show

I am sold out

I'm sold out

With every single

Step that I take now

With every drop of blood

Left in my veins

I'm gonna be making it count

I am sold out