文件读写之json、pickle、shelve的使用

我们在文件写入和读取时,总会遇到一个问题,就是写入的必须是字符串型(str),读取的也是字符串型。那么,如果我们要写入的是一个字典或者是一个列表之类的,那怎么办呢?没关系,我们可以写入时用str()方法将写入的对象转换成字符串,在读取之后用eval()方法将读取的数据转换成写入前的那个类型。

这种方法没问题,但是是不是觉得有点麻烦呢,或者说是有点low呢。python提供了几个常用的库,来实现数据类型之间的转换。下面介绍一下这些库的使用方法。

一. json库的使用
import json
1. json.dumps()-->将json对象转化为文本字符串,例如:

a = {"a": 1, "b": {"name": "Jie", "age": 25}, "c": [3, 4, 5]}
c = json.dumps(a)
print(c, type(c)
#结果: {"a": 1, "b": {"name": "Jie", "age": 25}, "c": [3, 4, 5]} <class 'str'>

这儿a是一个字典,经过json.dumps()方法之后,结果为一个字符串,也就是说,如果我们要将a写入文件的话,那么可以直接用这种方法,得到一个字符串,然后就可以直接写入,而不用特意的str()了,例如

f.write(json.dumps(a))

可能你会说这和f.write(str(a)有什么不同吗,效果是一样的,但是你不就多学了一种方法吗,何况json用来读写文件只是它 的用途之一而已。json有个专门的写入文件的方法,json.dump(a, f),注意,这儿时dump,前面说的是dumps,写入的效果是一样的。

2. json.loads()-->将文本字符串转化为json对象

这个方法的一个实际应用就是在读取文件时,正常的读取得到的是字符串,那么既然之前我都用json.dump()写入的,现在我想直接就读取到这个a(字典),那么就可以

with open('data.json', 'r', encoding='utf-8') as f:
    c = json.loads(f.read())
    print(c, type(c))

运行结果为{'a': 1, 'b': {'name': 'Jie', 'age': 25}, 'c': [3, 4, 5]} <class 'dict'>,这样就实现了写入什么类型,就读取到什么类型。如果说使用str()转化的方法写入的话,那你读取到的也是一个字符串,假如你现在要得到这个字典里的age的值,那你是不是要eval(c)['b']['age']这样,如果读取到的这个数据用到的不多就还好,一旦它在项目中多处用到,那你可能会在其他的地方忘记了它的原始类型,你就直接把它当做一个字典处理(实际上它是一个字符串),这样效率就很低了。

类似上面的json的写入方法,这个读取也有一个专门的方法

c = json.load(f),结果是一样的。

3. json格式可以理解为就是列表和字典的自由组合形式
4. 键值对的索引,例如data['姓名']也可以data.get('姓名'),推荐使用第二种,因为如果键不存在,这样也不会报错,返回一个None。get()方法也可以加入第二个参数,如果键没有找到的话,不是返回空,而是返回你加入的那个参数,例如data.get('姓名', '汤姆')
5. 值得注意的事,JSON的数据需要用双引号,不能用单引号,否则会报json.decoder.JSONecodeError错,这个问题之前我一直没注意到,错了我也半天找不到原因,所以尽量还是用双引号。
6. json写入文件不能显示中文,在将json对象转为字符串时,会用unicode来编码json中的中文,所以为了在文件中显示的也是中文,可以这样
    json.dump(data, f, ensure_ascii=False) ,这儿的ensure_ascii=False就是控制写入的中文可以正常显示。
7. dumps()里除了可以传入json对象,ensure_ascii外,还可以传入一个indent,indent的值就是写入文件时的缩进的长度

二. pickle库的使用

pickle和json的使用方法很像,同样是有dumps,dump,load,和loads方法,特别值得注意的就是pickle时以二进制来操作的,所以不管是文件写入还是文件读取都是以二进制的方式,比如: "rb","wb"等。

import pickle
1. pickle写入文件或打开文件的形式都是二进制类型,比如

with open('data.txt', 'wb') as f:

写入文件同样有两种方法,

    f.write(pickle.dumps(a))
    pickle.dump(a, f)
2. pickle写入的文件显示是不正常的,什么叫不正常,就是写入的文件,显示的像是一堆乱码。比如上面定义的那个字典a,写入之后显示的是

€}q (X   aqKX   bq}q(X   nameqX   JieqX   ageqKuX   cq]q(KKKeu.

可能你会以为,既然它是以二进制的方式写入,为什么在文件中不是以二进制显示呢,这个就不深究了,只要知道读取出来的数据是可以正常正常显示的就OK了。

3. pickle没有显示中文的ensure_ascii参数,但是可以pickle.dumps(data, 3)直接传入一个数字,表示缩进的字符数
4. 在json中,打开文件时可以使用encoding参数来确定编码格式,但是pickle打开文件不能encoding="utf-8"或是其他,默认就行

上面的json和pickle模块有一个缺点,就是只能写入一个数据,否则会报错。而且用json写入,就必须用json读取,不能用pickle或者是其他的方法。
           那么有时候确实需要写入多个数据怎么办?下面这个模块就支持多个读取,多个写入

三. shelve库的使用

import shelve
1. 具体的使用方法,数据写入文件方法如下

import shelve
import datetime

name = ["alan", "rain", "test"]
info = {"age": 20, "job": "IT"}
f = shelve.open('shelve_text')
f["name"] = name  # 持久化列表(写入)
f["info"] = info
f["date"] = datetime.datetime.now()  # 记录当前时间,写入
f.close()

读取文件的方法如下

f1 = shelve.open('shelve_text')
print(f1.get("name"))
print(f1.get('date'))
data = f1.get('info')
print(data['age'])
print(f1.items())

运行结果

['alan', 'rain', 'test']
2018-09-07 06:49:06.036216
20
2. 注意,这个方法打开文件,写入文件,读取文件的方式均和常规的不一样(是shelve.open()),而且文件没有后缀,原因是因为用这种方法写入的话,就会产生三个文件,后缀是.bak, .dat, .dir,以上面的为例,写入后文件中的内容是

'name', (0, 41)
'info', (512, 39)
'date', (1024, 44)

3. 而且如果读取的时候,例如f.get('data')不存在,则print是不会报错的

猜你喜欢

转载自blog.csdn.net/wtwcsdn123/article/details/82469622