Python 读取二进制平面文件并跳过字节

Python 读取二进制平面文件并跳过字节,python,numpy,Python,Numpy,我有一个二进制文件,它将数据组织成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 是否有一

我有一个二进制文件,它将数据组织成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方法允许我指定从缓冲区读取哪些字节?

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

最简单的方法可能是加载整个文件并将所需列子集:

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()
这里,
\u 1
\u 2
用于以1字节而不是4字节的分辨率丢弃不需要的字节

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

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

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
,因为一旦内存映射关闭,底层缓冲区就会失效,可能会导致segfault。

从哪里获得的值,如75100,(250100)?@datta。300/4, 400/4, 1000/4. 75实际上应该是76,因为偏移是304@datta. 我已经说得很清楚了。250应该是1000。这只是块计数。虽然这样做有效,但我发现它比使用
np.fromfile
和。然后我可以像这样索引和复制:
np.fromfile(f,dtype=my_dtype)['data'].copy()
这与post中的顶部答案非常相似,我可以按字段名排除所有剩余的数据。@datta。结构化数组是否比
np.fromfile(filename,dtype=np.uint32)[304//4::400//4]
快?而且,读取整个文件肯定会更快。使用内存映射速度较慢,但它可以让您在不崩溃的情况下读取非常大的文件。