我有一个二进制文件,包含一个标题,然后是一个记录列表。每个记录是一个 n 个无符号整数的列表,后跟一个 n 个有符号整数的列表。每个记录的 n 不同。无符号整数是变量 x 的值,有符号整数是变量 y 的值。例如,数据可能看起来像这样
4 3 1 5 -10 50 40 30
4 5 6 30 -25 100
5 4 30 55
6 4 6 7 4 -20 30 30 -50 60
我需要读取该文件并将每个记录存储到( n ,2)numpy数组中,其中第一列包含 x 值,第二列包含 y 值。然后,我想将所有数组存储到一个容器numpy数组中。最后,我应该有类似的东西
np.array([
np.array([[4, -10], [3, 50], [1, 40], [5, 30]]),
np.array([[4, 30], [5, -25], [6, 100]]),
np.array([[5, 30], [4, 55]]),
array([], shape=(0, 2)),
np.array([[6, -20], [4, 30], [6, 30], [7, -50], [4, 60]])
])
二进制文件大约200 MB,包含大约1000万条记录。每个记录的长度在标头数据中提供,我将其存储在lengths
数组中。请注意,某些记录可能为空,长度为0。
现在,我有一个使用struct.unpack的有效解决方案,但这确实很慢(读取文件需要花费几分钟)。我遍历lengths
数组并运行read_single_record
函数。
def read_single_record(f, length, x_fmt, y_fmt):
"""x_fmt and y_fmt are tuples of
(struct format character, size in bytes).
"""
raw = f.read(length)
n_vals = length // (x_fmt[1] + y_fmt[1])
val = struct.unpack(
f'{n_vals}' + x_fmt[0] + f'{n_vals}' + y_fmt[0], raw)
val = np.array(val, dtype=np.int16).reshape((n_vals, 2), order='F')
# do some more data processing
# ...
return val
records = np.empty(nb_records, dtype='object')
for i, length in enumerate(lengths):
records[i] = read_single_record(f, length, x_fmt, y_fmt)
我已经看到others suggest在使用np.fromfile,但是我不太确定如何在可变长度的记录中使用它。
从我的二进制文件中读取可变长度记录的最有效方法是什么?