相当于JavaScript的DataView的Python

时间:2019-05-21 16:34:14

标签: javascript python-3.x

我从base-64编码的字符串中加载字节数组,然后解析它。

不过,值是以不同的方式编码的,我想复制DataView的行为。

示例:

function parse(data){
    view = new DataView(data.buffer);

    return {
        headerSize : view.getUint8(0),
        numberOfPlanes : view.getUint16(1, true),
        width: view.getUint16(3, true),
        height: view.getUint16(5, true),
        offset: view.getUint16(7, true)
    };
}

用法:

data = new Uint8Array([8, 96, 0, 0, 2, 0, 1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
parse(data)

返回{headerSize: 8, numberOfPlanes: 96, width: 512, height: 256, offset: 8}

稍后,我需要使用DataView.getFloat32

现在我有这样的东西:

def get_bin(a):
    ba = bin(a)[2:]
    return "0" * (8 - len(ba)) + ba


def getUInt16(arr, ind):
    a = arr[ind]
    b = arr[ind + 1]
    return int(get_bin(b) + get_bin(a), 2)

def getFloat32(arr, ind):
    return bin_to_float("".join(get(i) for i in arr[ind : ind + 4][::-1]))


def bin_to_float(binary):
    return struct.unpack("!f", struct.pack("!I", int(binary, 2)))[0]

但是图书馆可能更有效,更通用

浮动示例:[111, 62, 163, 36]应该产生7.079574826789837e-17

1 个答案:

答案 0 :(得分:1)

这应该涵盖您足够的用例,或者至少可以使您进行微小的更改。希望您可以按照我的做法做些事情,但随时可以提问。

from functools import reduce
import struct
class DataView:
    def __init__(self, array, bytes_per_element=1):
        """
        bytes_per_element is the size of each element in bytes.
        By default we are assume the array is one byte per element.
        """
        self.array = array
        self.bytes_per_element = 1

    def __get_binary(self, start_index, byte_count, signed=False):
        integers = [self.array[start_index + x] for x in range(byte_count)]
        bytes = [integer.to_bytes(self.bytes_per_element, byteorder='little', signed=signed) for integer in integers]
        return reduce(lambda a, b: a + b, bytes)

    def get_uint_16(self, start_index):
        bytes_to_read = 2
        return int.from_bytes(self.__get_binary(start_index, bytes_to_read), byteorder='little')

    def get_uint_8(self, start_index):
        bytes_to_read = 1
        return int.from_bytes(self.__get_binary(start_index, bytes_to_read), byteorder='little')

    def get_float_32(self, start_index):
        bytes_to_read = 4
        binary = self.__get_binary(start_index, bytes_to_read)
        return struct.unpack('<f', binary)[0] # <f for little endian


def parse(byte_array):
    d = DataView(byte_array)
    return {
        "headerSize": d.get_uint_8(0),
        "numverOfPlanes": d.get_uint_16(1),
        "width": d.get_uint_16(3),
        "hieght": d.get_uint_16(5),
        "offset": d.get_uint_16(7),
    }

result = parse([8, 96, 0, 0, 2, 0, 1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
import json
print(json.dumps(result, indent=2))

d = DataView([111, 62, 163, 36])
d.get_float_32(0)

输出:

{
  "headerSize": 8,
  "numverOfPlanes": 96,
  "width": 512,
  "hieght": 256,
  "offset": 8
}
7.079574826789837e-17