【问题标题】:Read binary flatfile and skip bytes读取二进制平面文件并跳过字节
【发布时间】:2020-03-02 17:22:37
【问题描述】:

我有一个二进制文件,其中的数据组织成 400 字节组。我想从位置 304 到位置 308 的字节构建np.uint32 类型的数组。但是,我找不到 NumPy 提供的让我选择要读取的字节的方法,只有numpy.fromfile 中定义的初始偏移量。

例如,如果我的文件包含 1000 组 400 字节,我需要一个大小为 1000 的数组,这样:

arr[0] = bytes 304-308
arr[1] = bytes 704-708
...
arr[-1] = bytes 399904 - 399908

是否有一个 NumPy 方法可以让我指定从缓冲区读取哪些字节?

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    另一种改写您正在寻找的内容的方法(稍微)是说您想读取从偏移量 304 开始的 uint32 数字,步长为 400 字节。 np.fromfile 没有提供插入自定义步幅的参数(尽管它可能应该)。你有几个不同的选择。

    最简单的可能是加载整个文件并子集您想要的列:

    data = np.fromfile(filename, dtype=np.uint32)[304 // 4::400 // 4].copy()
    

    如果您想更好地控制字节的精确定位(例如,如果偏移量或块大小不是 4 的倍数),您可以改用结构化数组:

    dt = np.dtype([('_1', 'u1', 304), ('data', 'u4'), ('_2', 'u1', 92)])
    data = np.fromfile(filename, dtype=dt)['data'].copy()
    

    这里,_1_2 用于丢弃不需要的字节,分辨率为 1 字节而不是 4。

    加载整个文件通常比在读取之间查找要快得多,因此这些方法对于适合内存的文件可能是可取的。如果不是这种情况,您可以使用内存映射或完全自主开发的解决方案。

    内存映射可以通过 Python 的 mmap 模块实现,并使用 buffer 参数包装在 ndarray 中,或者您可以使用为您执行此操作的 np.memmap 类:

    mm = np.memmap(filename, dtype=np.uint32, mode='r', offset=0, shape=(1000, 400 // 4))
    data = np.array(mm[:, 304 // 4])
    del mm
    

    使用原始mmap 可以说效率更高,因为您可以指定直接查看地图的步幅和偏移量,从而跳过所有额外数据。它也更好,因为您可以使用不是np.uint32 大小的倍数的偏移量和步幅:

    with open(filename, 'rb') as f, mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ) as mm:
        data = np.ndarray(buffer=mm, dtype=np.uint32, offset=304, strides=400, shape=1000).copy()
    

    需要对copy 进行最终调用,因为一旦关闭内存映射,底层缓冲区就会失效,可能会导致段错误。

    【讨论】:

    • 你从哪里得到像 75, 100, (250, 100) 这样的值?
    • @datta。 300/4、400/4、1000/4。 75 实际上应该是 76,因为偏移量是 304
    • @datta。我已经明确了。 250 应该是 1000。这只是块数。
    • 虽然这可行,但我发现它比使用 np.fromfilestructured array 慢。然后我可以像这样索引和复制:np.fromfile(f, dtype=my_dtype)['data'].copy() 这与this 帖子中的最佳答案非常相似,我可以通过字段名称排除所有剩余的数据。
    • @datta。结构化数组比np.fromfile(filename, dtype=np.uint32)[304 // 4::400 // 4] 快吗?此外,读取整个文件肯定会更快。使用内存映射有点慢,但它可以让您读取非常大的文件而不会崩溃。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-06
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    • 2016-03-28
    • 2012-07-11
    • 1970-01-01
    相关资源
    最近更新 更多