Python读取大二进制文件的一部分

时间:2018-07-28 10:34:45

标签: python debugging runtime-error binaryfiles

我有很大的二进制文件(大小约为2.5Gb )。它包含标头(大小为336字节)和类型为int32的地震信号数据(x,y和z通道)。离散数量为223200 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中的函数运行脚本,则会收到错误消息:

  

回溯(最近通话最近):文件   “ D:/AppsBuilding/test/testReadBaikal8.py”,第41行,在       信号_2 =读取(路径=路径,开始_时刻= 216000000,结束_时刻= 219599999)文件   阅读中的“ D:/AppsBuilding/test/testReadBaikal8.py”,第27行       count = moment_count * 3)OSError:获取文件位置失败

但是如果我运行带有以下参数的脚本:start_moment = 7200000,end_moment = 10799999都可以。 在我的PC上安装了Windows7 32bit。记忆体大小为1.95Gb 请帮我解决这个问题。

2 个答案:

答案 0 :(得分:0)

将文件分成小段,每小段释放一次内存    内容已处理

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

答案 1 :(得分:0)

我不使用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)