[英]How to read part of binary file with numpy?
我正在将 matlab 脚本转换为 numpy,但是在从二进制文件读取数据时遇到了一些问题。 使用fromfile
跳过文件开头时是否有fromfile
于fseek
的内容? 这是我需要做的提取类型:
fid = fopen(fname);
fseek(fid, 8, 'bof');
second = fread(fid, 1, 'schar');
fseek(fid, 100, 'bof');
total_cycles = fread(fid, 1, 'uint32', 0, 'l');
start_cycle = fread(fid, 1, 'uint32', 0, 'l');
谢谢!
您可以以正常方式对文件对象使用 seek,然后在fromfile
使用此文件对象。 这是一个完整的例子:
import numpy as np
import os
data = np.arange(100, dtype=np.int)
data.tofile("temp") # save the data
f = open("temp", "rb") # reopen the file
f.seek(256, os.SEEK_SET) # seek
x = np.fromfile(f, dtype=np.int) # read the data into numpy
print x
# [64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
# 89 90 91 92 93 94 95 96 97 98 99]
可能有更好的答案……但是当我遇到这个问题时,我已经想分别访问一个文件的不同部分,这给了我一个简单的解决方案。
例如, chunkyfoo.bin
是一个由 6 字节标头、1024 字节numpy
数组和另一个 1024 字节numpy
数组组成的文件。 你不能只打开文件并寻找 6 个字节(因为numpy.fromfile
做的第一件事是lseek
回到 0)。 但是,你可以mmap
的文件,并使用fromstring
改为:
with open('chunkyfoo.bin', 'rb') as f:
with closing(mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ)) as m:
a1 = np.fromstring(m[6:1030])
a2 = np.fromstring(m[1030:])
这听起来正是您想要做的。 当然,除了在现实生活中, a1
和a2
的偏移量和长度可能取决于标题,而不是固定的注释。
标头只是m[:6]
,您可以通过显式将其分开、使用struct
模块或read
数据后执行的任何其他操作来解析它。 但是,如果您愿意,您可以在构造m
之前或之后显式地从f
seek
和read
,甚至可以对m
进行相同的调用,它会起作用,而不会影响a1
和a2
。
我为另一个非numpy
相关项目所做的替代方法是创建一个包装文件对象,如下所示:
class SeekedFileWrapper(object):
def __init__(self, fileobj):
self.fileobj = fileobj
self.offset = fileobj.tell()
def seek(self, offset, whence=0):
if whence == 0:
offset += self.offset
return self.fileobj.seek(offset, whence)
# ... delegate everything else unchanged
我通过在构建时生成一个属性list
并在__getattr__
使用它来完成“委托其他一切不变”,但你可能想要一些不那么hacky的东西。 numpy
仅依赖于类文件对象的少数方法,我认为它们已被正确记录,因此只需明确委派这些方法即可。 但我认为mmap
解决方案在这里更有意义,除非您试图机械地移植一堆基于显式seek
的代码。 (您可能认为mmap
还可以让您选择将其保留为numpy.memmap
而不是numpy.array
,这让numpy
可以更好地控制分页等/反馈等。但实际上很难获得numpy.memmap
和mmap
一起工作。)
当我必须在异构二进制文件中任意读取时,这就是我所做的。
numpy的允许通过改变来解释任意波形方式的比特模式D型阵列的。 问题中的 Matlab 代码读取一个char
和两个uint
。
阅读这篇论文(用户级别的简单阅读,而不是科学家),了解通过更改数组的 dtype、步长和维度可以实现的目标。
import numpy as np
data = np.arange(10, dtype=np.int)
data.tofile('f')
x = np.fromfile('f', dtype='u1')
print x.size
# 40
second = x[8]
print 'second', second
# second 2
total_cycles = x[8:12]
print 'total_cycles', total_cycles
total_cycles.dtype = np.dtype('u4')
print 'total_cycles', total_cycles
# total_cycles [2 0 0 0] !endianness
# total_cycles [2]
start_cycle = x[12:16]
start_cycle.dtype = np.dtype('u4')
print 'start_cycle', start_cycle
# start_cycle [3]
x.dtype = np.dtype('u4')
print 'x', x
# x [0 1 2 3 4 5 6 7 8 9]
x[3] = 423
print 'start_cycle', start_cycle
# start_cycle [423]
numpy.fromfile()
有一个相当新的特性
偏移INT
与文件当前位置的偏移量(以字节为单位)。 默认为 0。仅允许用于二进制文件。
1.17.0 版中的新功能。
import numpy as np
import os
data = np.arange(100, dtype=np.int32)
data.tofile("temp") # save the data
x = np.fromfile("temp", dtype=np.int32, offset=256) # use the offset
print (x)
# [64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
# 89 90 91 92 93 94 95 96 97 98 99]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.