Python中与JavaScript的DataView相对应的是什么?

3

我从一个base-64编码的字符串中加载了一个字节数组,现在我想解析它。

然而,值以不同的方式进行编码,我想复制 DataView 的行为。

示例:

Original Answer翻译成"最初的回答"

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个回答

4
这应该足够覆盖你的大部分使用情况,或者至少可以让你达到可以进行小的更改的程度。希望你能够在一定程度上理解我的操作,但如果有问题,请随时提问。最初的回答:
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

谢谢!实际上,我卡在float32这里,因为int8只是一个值,int16如你所见我已经成功复制了,但是float32更难一些,如果你能帮忙看一下,我会非常感激! - ted
@ted,你能添加一个示例输入和输出,这样我就可以检查我的工作了吗?我不知道浮点数通常的行为。 - Error - Syntactical Remorse
但是你需要添加错误处理(尤其是索引超出范围)。 - Error - Syntactical Remorse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接