Python 读取大型二进制文件的一部分
Python Read part of large binary file
我有很大的二进制文件(大小~2.5Gb)。它包含 header(大小 336 字节)和类型为 int32 的地震信号数据(x、y 和 z 通道)。离散数为 223 200 000。
我需要阅读部分信号。例如,我想在离散区间 [216 000 000, 219 599 999] 中获取部分信号。
我写了函数:
def reading(path, start_moment, end_moment):
file_data = open(path, 'rb')
if start_moment is not None:
bytes_value = start_moment * 4 * 3
file_data.seek(336 + bytes_value)
else:
file_data.seek(336)
if end_moment is None:
try:
signals = np.fromfile(file_data, dtype=np.int32)
except MemoryError:
return None
finally:
file_data.close()
else:
moment_count = end_moment - start_moment + 1
try:
signals = np.fromfile(file_data, dtype=np.int32,
count=moment_count * 3)
except MemoryError:
return None
finally:
file_data.close()
channel_count = 3
signal_count = signals.shape[0] // channel_count
signals = np.reshape(signals, newshape=(signal_count, channel_count))
return signals
如果我 运行 使用 PyCharm IDE 中的函数编写脚本,我得到错误:
Traceback (most recent call last): File
"D:/AppsBuilding/test/testReadBaikal8.py", line 41, in
signal_2 = reading(path=path, start_moment=216000000, end_moment=219599999) File
"D:/AppsBuilding/test/testReadBaikal8.py", line 27, in reading
count=moment_count * 3) OSError: obtaining file position failed
但是如果我 运行 脚本的参数是:start_moment=7200000, end_moment=10799999 都可以。
在我的电脑上安装了 Windows7 32 位。内存大小为 1.95Gb
请帮我解决这个问题。
将文件分成小段,每个小段后释放内存
一段内容已处理
def read_in_block(file_path):
BLOCK_SIZE = 1024
with open(file_path, "r") as f:
while True:
block = f.read(BLOCK_SIZE)
if block:
yield block
else:
return
print block
我不使用 Numpy,但我没有发现您的代码有任何明显的错误。但是,您说该文件的大小约为 2.5 GB。三元组索引 219,599,999 需要至少 2.45 GB 的文件:
$ calc
; 219599999 * 4 * 3
2635199988
; 2635199988 / 1024^3
~2.45422123745083808899
您确定您的文件真的有那么大吗?
我也不使用 MS Windows,但以下玩具程序对我有用。第一个创建一个模仿您的结构的数据文件。第二个表明它可以读取最终的数据三元组。如果你 运行 这些在你的系统上会发生什么?
fh = open('x', 'wb')
fh.write(b'0123456789')
for i in range(0, 1000):
s = bytes('{:03d}'.format(i), 'ascii')
fh.write(b'a' + s + b'b' + s + b'c' + s)
从文件x
读取数据:
fh = open('x', 'rb')
triplet = 999
fh.seek(10 + triplet * 3 * 4)
data = fh.read(3 * 4)
print(data)
我有很大的二进制文件(大小~2.5Gb)。它包含 header(大小 336 字节)和类型为 int32 的地震信号数据(x、y 和 z 通道)。离散数为 223 200 000。 我需要阅读部分信号。例如,我想在离散区间 [216 000 000, 219 599 999] 中获取部分信号。 我写了函数:
def reading(path, start_moment, end_moment):
file_data = open(path, 'rb')
if start_moment is not None:
bytes_value = start_moment * 4 * 3
file_data.seek(336 + bytes_value)
else:
file_data.seek(336)
if end_moment is None:
try:
signals = np.fromfile(file_data, dtype=np.int32)
except MemoryError:
return None
finally:
file_data.close()
else:
moment_count = end_moment - start_moment + 1
try:
signals = np.fromfile(file_data, dtype=np.int32,
count=moment_count * 3)
except MemoryError:
return None
finally:
file_data.close()
channel_count = 3
signal_count = signals.shape[0] // channel_count
signals = np.reshape(signals, newshape=(signal_count, channel_count))
return signals
如果我 运行 使用 PyCharm IDE 中的函数编写脚本,我得到错误:
Traceback (most recent call last): File "D:/AppsBuilding/test/testReadBaikal8.py", line 41, in signal_2 = reading(path=path, start_moment=216000000, end_moment=219599999) File "D:/AppsBuilding/test/testReadBaikal8.py", line 27, in reading count=moment_count * 3) OSError: obtaining file position failed
但是如果我 运行 脚本的参数是:start_moment=7200000, end_moment=10799999 都可以。 在我的电脑上安装了 Windows7 32 位。内存大小为 1.95Gb 请帮我解决这个问题。
将文件分成小段,每个小段后释放内存 一段内容已处理
def read_in_block(file_path):
BLOCK_SIZE = 1024
with open(file_path, "r") as f:
while True:
block = f.read(BLOCK_SIZE)
if block:
yield block
else:
return
print block
我不使用 Numpy,但我没有发现您的代码有任何明显的错误。但是,您说该文件的大小约为 2.5 GB。三元组索引 219,599,999 需要至少 2.45 GB 的文件:
$ calc
; 219599999 * 4 * 3
2635199988
; 2635199988 / 1024^3
~2.45422123745083808899
您确定您的文件真的有那么大吗?
我也不使用 MS Windows,但以下玩具程序对我有用。第一个创建一个模仿您的结构的数据文件。第二个表明它可以读取最终的数据三元组。如果你 运行 这些在你的系统上会发生什么?
fh = open('x', 'wb')
fh.write(b'0123456789')
for i in range(0, 1000):
s = bytes('{:03d}'.format(i), 'ascii')
fh.write(b'a' + s + b'b' + s + b'c' + s)
从文件x
读取数据:
fh = open('x', 'rb')
triplet = 999
fh.seek(10 + triplet * 3 * 4)
data = fh.read(3 * 4)
print(data)