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

如何在内存中压缩、保存与加载大型数据?

解决方案:给压缩块加「长度标记」实现内存中分块读写

我太懂这种尴尬了——巨型字典把内存占得满满当当,连整体pickle或者压缩都做不了,好不容易找到分块写入内存的方法,结果读取的时候卡壳了,因为压缩块没分界根本拆不开!核心问题就是你之前的写入逻辑没给每个压缩块做明确的边界标记,导致读取时无法判断每个块的起止位置。下面给你一套完整的内存中分块读写方案:

第一步:补全带边界标记的分块写入逻辑

如果你的原有写入代码没有记录每个压缩块的长度,得先改成下面这种(不然现有数据没法正确读取):

import zlib
import struct
import pickle
from io import BytesIO
import numpy as np

def write_large_dict_to_memory(large_dict):
    buffer = BytesIO()
    # 自定义分块大小,根据你的内存剩余空间调整,比如每1000个键值对为一块
    chunk_size = 1000
    items = list(large_dict.items())
    
    for i in range(0, len(items), chunk_size):
        # 切分字典为小分块
        chunk = dict(items[i:i+chunk_size])
        # 序列化分块(用pickle转成字节流)
        serialized_chunk = pickle.dumps(chunk)
        # zlib压缩
        compressed_chunk = zlib.compress(serialized_chunk)
        
        # 关键操作:先写入压缩块的长度(用struct打包成4字节无符号整数)
        # 这是读取时的"分界锚点"
        buffer.write(struct.pack('I', len(compressed_chunk)))
        # 再写入压缩后的块数据
        buffer.write(compressed_chunk)
    
    # 将缓冲区指针移到开头,方便后续读取
    buffer.seek(0)
    return buffer

第二步:对应的分块读取逻辑

有了块长度标记后,读取就很清晰了——循环读取长度标记,再读取对应长度的压缩数据,解压合并即可:

def read_large_dict_from_memory(buffer):
    large_dict = {}
    buffer.seek(0)
    
    while True:
        # 先读取4字节的块长度标记
        len_bytes = buffer.read(4)
        if not len_bytes:
            # 读到缓冲区末尾,退出循环
            break
        
        # 解析出压缩块的实际长度
        compressed_len = struct.unpack('I', len_bytes)[0]
        # 读取对应长度的压缩块数据
        compressed_chunk = buffer.read(compressed_len)
        
        # 解压+反序列化分块
        serialized_chunk = zlib.decompress(compressed_chunk)
        chunk = pickle.loads(serialized_chunk)
        
        # 合并到总字典
        large_dict.update(chunk)
    
    return large_dict

关键说明

  1. 边界标记的作用:用struct.pack('I', ...)把每个压缩块的长度转成固定4字节的二进制数据,相当于给每个块加了一个"长度标签",读取时先读标签就知道接下来要读多少字节的压缩数据,完美解决块分界问题。
  2. 分块大小调整:chunk_size可以根据你的内存情况灵活调整——如果单个分块解压后还是占太多内存,就把数值调小一点,反之可以调大提升效率。
  3. 序列化/压缩一致性:读写时必须用相同的工具链——比如写入用zlib压缩、pickle序列化,读取时也必须对应使用zlib解压、pickle反序列化,否则会报错。

注意事项

如果你的原有写入数据没有加这个长度标记,那很遗憾,现有数据可能无法正确拆分读取了——因为压缩后的字节流没有任何分界特征,无法判断一个块的结束位置。这种情况下只能重新用带长度标记的逻辑写入数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:02:56