You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用np.memmap读取大字节文件资源不足,流式读取报UnicodeDecodeError如何解决?

问题根因

你遇到的报错核心是误用了numpy.fromfile()接口:该方法的入参要求为文件路径字符串或文件对象,你传入的是fp.read()返回的bytes字节流对象,numpy会默认将该字节流尝试解码为UTF-8格式的文件名,遇到非UTF-8的二进制字节自然抛出解码错误。

可行解决方案

直接使用numpy.frombuffer()解析读取到的字节流即可,同时需要处理字节对齐问题:你使用的np.int16单元素占2字节,每次读取的块长度需要对齐单元素字节数,避免截断单个元素产生解析错误。
修正后的流式读取代码如下:

import numpy as np

# 配置数据格式、块大小
dtype = np.int16
single_elem_size = dtype.itemsize
# 单次读取2MB数据,可根据自身可用内存调整大小,越大整体读取效率越高
read_chunk_size = 1024 * 1024 * 2
# 存储上一轮读取剩余的不足单元素长度的字节
leftover_bytes = b''

with open(filename, mode='rb') as fp:
    while True:
        current_chunk = fp.read(read_chunk_size)
        # 读到文件末尾直接退出循环
        if not current_chunk:
            break
        # 拼接上轮残留字节和当前读取的字节
        total_bytes = leftover_bytes + current_chunk
        # 计算可完整解析为int16的有效字节长度,必须是单元素字节数的整数倍
        valid_byte_len = (len(total_bytes) // single_elem_size) * single_elem_size
        # 解析有效字节为numpy数组
        int_chunk = np.frombuffer(total_bytes[:valid_byte_len], dtype=dtype)
        # 存储本轮不足单元素长度的残留字节,下一轮拼接处理
        leftover_bytes = total_bytes[valid_byte_len:]

        # 此处添加你对int_chunk的业务处理逻辑,例如统计、写入其他文件等
        # process_chunk(int_chunk)

# 全量读取完成后如果仍有残留字节,说明文件本身长度不是int16元素的整数倍,可按需处理
if leftover_bytes:
    print(f"文件末尾存在{len(leftover_bytes)}个无法解析为int16的残留字节")

该方案优势是np.frombuffer直接基于字节流解析,不会产生额外内存拷贝,性能开销极低。

替代思路

如果你读取的是标准.npy格式的numpy二进制文件,可以直接使用numpy内置的懒加载接口,无需自己实现流式读取逻辑,只会在访问对应数组切片时才加载数据到内存,不会占用过多系统资源:

import numpy as np

# 只读模式懒加载大文件
arr = np.lib.format.open_memmap(filename, mode='r', dtype=np.int16)
# 按需切片读取,单次读取10万条数据,可自行调整步长
for idx in range(0, len(arr), 100000):
    current_chunk = arr[idx: idx+100000]
    # 处理current_chunk

内容的提问来源于stack exchange,提问作者albusSimba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 03:15:02