另一种改写您正在寻找的内容的方法(稍微)是说您想读取从偏移量 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 进行最终调用,因为一旦关闭内存映射,底层缓冲区就会失效,可能会导致段错误。