Talk is cheap. Show me the code.
Numpy解析
import numpy as np
class BinaryReaderError(IndexError):
pass
class BinaryReader:
def __init__(self, data, endianness="<"):
self.data = data
self.endianness = endianness
self.offset = 0
def read(self, fmt, count=1):
dt = np.dtype(fmt).newbyteorder(self.endianness)
self.check_offset(self.offset + dt.itemsize * count)
value = np.frombuffer(self.data, dt, count, self.offset)
self.offset += dt.itemsize * count
return value
def read_int8(self):
return self.read("b")[0]
def read_uint8(self):
return self.read("B")[0]
def read_uint16(self):
return self.read("h")[0]
def read_uint16(self):
return self.read("H")[0]
def read_int32(self):
return self.read("i")[0]
def read_uint32(self):
return self.read("I")[0]
def read_int64(self):
return self.read("q")[0]
def read_uint64(self):
return self.read("Q")[0]
def read_float32(self):
return self.read("f")[0]
def read_float64(self):
return self.read("d")[0]
def read_bool8(self):
return self.read("?")[0]
def read_vec2f(self):
return self.read("f", 2)
def read_vec3f(self):
return self.read("f", 3)
def read_vec4f(self):
return self.read("f", 4)
def read_vec4b(self):
return self.read("b", 4)
def read_quat(self):
return self.read("f", 4)
def read_mat2(self):
return self.read("f", 4)
def read_mat3(self):
return self.read("f", 9)
def read_mat4(self):
return self.read("f", 16)
def read_string(self, n):
return self.read_bytes(n).decode()
def read_bytes(self, n):
self.check_offset(self.offset + n)
value = self.data[self.offset:self.offset+n]
self.offset += n
return value
def read_float16(self):
return self.read("f2")[0]
def seek(self, offset):
self.check_offset(offset)
self.offset = offset
def skip(self, offset):
self.seek(self.offset + offset)
def check_offset(self, offset):
if offset < 0 or offset > len(self.data):
raise BinaryReaderError("Binary reader out of bounds")
def finished(self):
return self.offset >= len(self.data)
Struct解析
from io import BufferedReader, BytesIO
from struct import unpack
class Reader(BufferedReader):
def __init__(self, initial_bytes: bytes, endian: str = '>'):
super().__init__(BytesIO(initial_bytes))
self.endian = endian
def readUInt64(self):
return unpack(self.endian + 'Q', self.read(8))[0]
def readInt64(self):
return unpack(self.endian + 'q', self.read(8))[0]
def readUInt32(self):
return unpack(self.endian + 'I', self.read(4))[0]
def readInt32(self):
return unpack(self.endian + 'i', self.read(4))[0]
def readUInt16(self):
return unpack(self.endian + 'H', self.read(2))[0]
def readInt16(self):
return unpack(self.endian + 'h', self.read(2))[0]
def readUInt8(self):
return unpack(self.endian + 'B', self.read(1))[0]
def readInt8(self):
return unpack(self.endian + 'b', self.read(1))[0]
def readFloat(self):
return unpack(self.endian + "f", self.read(4))[0]
readULong = readUInt64
readLong = readInt64
readUShort = readUInt16
readShort = readInt16
readUByte = readUInt8
readByte = readInt8
def readChar(self, length: int = 1):
return self.read(length).decode('utf-8')
def readString(self):
return self.readChar(self.readUInt32())
def _skip(self,off):
self.read(off)