所以我在关于使用随机文件的书中遵循指南,并使用以下代码来保存一些对象
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)找出单个记录的大小?
答案 0 :(得分:1)
此代码的问题在于汽车对象在写入时会覆盖以前写入的汽车对象。这可以通过直接挑选列表来解决:
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对象保存到文件的最简单方法。
编辑:确保记录大小相同的最简单方法是不使用pickle。但是,您可以将记录的大小与记录一起存储:
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个记录而不遍历所有先前的记录。