繁体   English   中英

我如何使用散列和泡菜来保存/加载对象

[英]How do I use hashing and pickle to save/load objects

所以我正在遵循一本关于使用随机文件的书中的指南,并使用以下代码来保存一些对象

import pickle
from carRec import carRec

cars = [carRec(1, "Ford", "Escort"), carRec(2, "Ford", "Focus"), carRec(3, "Ford", "Mustang")]

#output to carsFile
carFile = open("carsRand.dat", "wb")

for i in range(0,3):
   address = hash(cars[i].vehicleID)
   carFile.seek(address)
   pickle.dump(cars[i], carFile)

carFile.close()

然后用于加载数据

import pickle
from carRec import carRec

carFile = open("cars.dat", "rb")
cars = []
counter = 1

try:
    while True:
        location = hash(counter)
        carFile.seek(location)
        cars.append(pickle.load(carFile))
        counter += 1
except EOFError:
    print("done")

carFile.close()  

问题是,当我尝试重新加载数据时,出现以下错误

_pickle.UnpicklingError: invalid load key, ''.

快速查看 dat 文件使我认为数据的写入工作不正常。 我相信,当使用散列和查找函数来确定写入/读取的位置时,您需要考虑记录的大小(以字节为单位)。 如果是这种情况,我如何 a) 确保所有记录的大小相同,以及 b) 找出单个记录的大小?

此代码的问题在于汽车对象在写入时会覆盖先前写入的汽车对象。 这可以通过直接酸洗列表来解决:

import pickle
with open("cars.dat", "wb") as f:
    pickle.dump(cars, f)

然后可以加载:

with open("cars.dat", "rb") as f:
    cars = pickle.load(f) 

如果您绝对必须单独腌制对象,则可以使用len(pickle.dumps(obj, -1))确定对象的腌制大小

此外,您是否考虑过使用shelve模块? 这是将简单的 Python 对象持久化到文件的最简单方法。

编辑:确保记录大小相同的最简单方法是不使用泡菜。 但是,您可以在记录旁边存储记录的大小:

import pickle
import struct

with open("cars.dat", "wb") as f:
    for car in cars:
        size = len(pickle.dumps(car, -1))
        f.write(struct.pack("<I", size))
        pickle.dump(car, f)

此代码在每条记录之前存储 4 个字节的长度信息。 然后可以使用struct.unpack("<I", f.read(4))[0]加载此长度数据

然后,您还可以将每个(长度、数据)对的偏移量存储在文件的开头,以允许读取第 n 条记录而无需遍历所有先前的记录。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM