python自学第七天博客记录 第十章文件与IO(2/26)

10.1打开文件

打开文件使用的是内置函数open
open有许多参数,在官方文档中open函数的定义如下:
open(file,mode=“r”,buffering=-1,encoding=None,errors=None,newline=None,closefd=True,opener=None)
open函数只有file函数是必须传递的,其他参数都要默认值,最简单的打开文件例子如下:

file_name = "10.1.1.py"
f = open(file_name)

10.1.1文件名模式
open函数的参数 mode十分重要,它指明了要以何种方式打开文件,使用不同的方式打开文件,即使操作相同,产生的效果也会有所不同。默认的模式是“r”,即以只读方式打开文件 可用模式如下:
书本185页

10.2文件基本操作

10.2.1读文件
如果只是希望读取整个文件并保存到一个字符串中,就可以使用read方法

f = open("222.txt")
txt = f.read()
print(txt)

read方法也可以传递参数,用于指定读取多少字符,例如:

f = open("222.txt")
txt = f.read(5)
print(txt)

10.2.2写文件
如要写文件,必须使用带“w”模式的方式打开文件。打开文件后可以使用文件对象write方法,将任意字符串写入文件中。write方法返回写入文件的字符串的长度,例如:

f = open("222.txt","w")
txt = "写入文件"
print(f.write(txt))

如果我们想在已有的文件内容后面追加内容,可以在打开文件时使用“a”模式,这样就能在文件中追加写入内容了例如:

from datetime import datetime
f = open("222.txt","a")
now = str(datetime.now())+"\n"
print(f.write(now))

每次运行这个试例,“222.txt”文件都会追加一行写入文件的时间信息

10.2.3执行读取文件
python为我们提供了一种按行读取文件内容的方法,使用readline函数可以逐行读取文件内容,例如:

f = open("222.txt","r")
print(f.readline())
print(f.readline())

readlines函数和read函数类似,都会读取整个文件,但是readlines函数会把文件内容按行切割,返回一个list列表对象。例如:

f = open("222.txt","r")
for line in f.readline():
    print(line)

这个会把文件“222.txt”中的日期一行一行地打印在屏幕上。注意:readlines函数会保留结尾的换行符,所以直接print列表元素会发现每次输出都跟随一个空白行
除了使用readline和readlines方法,还能直接迭送文件对象本身,例如:

f = open("222.txt","r")
for line in f:
    print(line)

10.2.4 按行写文件
python提供了writelines方法,把列表作为参数写入文件,不会添加换行符。
writelines方法接收一个参数,,这个参数必须是列表,列表的每个元素就是想写入的每行文本内容,但是我们在列表中需要自行添加换行符,例如:

f = open("222.txt","w")
lines = []
for i in range(10):
    lines.append(str(i))

f.writelines(lines)

这个运行后会在文件中生成0-9十个数字 而且不会被换行。

10.2.4 关闭文件
写入文件过程中随时会出现异常,可以使用try语句捕获可能出现的相关异常,然后进行对应的处理,调用close方法来关闭文件比较好,使用如下:

f = open("222.txt","w")
f.close()

为了安全起见,使用完文件之后一定要记得关闭文件,在使用try语句出现异常后,解释器会放弃之后的语句去执行catch捕获到异常的语句,所以建议close方法在finally语句中执行,保证无论是否有异常都会执行close方法并关闭文件 如:

f = None
try:
    f = open("222.txt","r")
    print(f.read())
except IOError:
    print("Error")
finally:
    if f:
        f.close()

每个打开的文件都要执行close方法关闭文件,但是有时候文件处理的逻辑比较复杂,很容易忘记关闭文件。有什么比较方便的方法能够确保文件会被关闭呢?
可以使用with语句来帮助我们自动调用close方法 如:

with open("222.txt","r")as f:
    content = f.read()
    print(content)

我们没有手动的去调用close函数,但是使用了with语句,会在执行完with语句之后执行close语句,让代码更简洁。

10.3StringIO和BytesIo

有时候并不需要真正地写入到文件中,只需要在内存中做读取写入即可。Python中的IO模块提供了对Str操作的StringIO函数。
要把str写入StringIO,我们要先创建一个StringIO对象,然后谢文件一样写入即可,例如:

from io import StringIO
f = StringIO()
f.write('hello')
f.write(' ')
f.write('world!!')
print(f.getvalue())

这个例子创建了StringIO对象,然后调用write方法写入数据,和文件操作几乎相同。getvalue方法用于获得写入后的str
要读取StringIO,可以先用一个str初始化StringIO,然后像读取文件一样读取,例如:

from io import StringIO
f = StringIO('Hello!\nworld!\nWelcome!')
while True:
    s = f.readline()
    if s == "":
        break
    print(s.strip())

执行结果如下:
Hello!
world!
Welcome!
StringIO的操作对象只能是str,如果要操作二进制数据,就需要使用BytesIO。
BytesIO实现在内存中读写bytes,可以先创建一个BytesIO,然后写入bytes例如:

from io import BytesIO
f = BytesIO()
f.write("您好".encode("utf-8"))
print(f.getvalue())
print(f.getvalue().decode("utf-8"))

执行结果如下:
b’\xe6\x82\xa8\xe5\xa5\xbd’
您好

注意写入的不是str,而是经过UTF-8的bytes
和StringIO类似,可以先用一个bytes初始化BytesIO,然后像读文件一样读取,例如:

from io import BytesIO
f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
print(f.read().decode("utf-8"))

执行结果:
中文

10.4序列化和反序列化

把变量从内存中变成可存储或传输的过程被称为序列化,可以把序列化后的内容写到磁盘或者传输到别的计算机上。反过来,我们把变量内容从序列化对象重新读取到内存的过程称为反序列化。

简单说就是:
序列化:将数据结构或者对象转换成二进制串的过程
反序列化:将序列化过程中产生的二进制串转回成数据结构或对象的过程。

10.4.1pickle模块
pickle他是标准库中的标准模块,它实现了一些基本数据的序列化和反序列化。
可以将程序中运行的对象信息保存到文件中,永久存储;可以从文件中恢复或者创建上次程序保存下来的对象。

pickle模块的dumps方法可以把对象序列化成bytes,例如:

import pickle
class Student:
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender

student1 = Student("小明",15,"男")
print(pickle.dumps(student1))

执行这个例子会打印出序列化后的bytes对象,pickle.dunos可以把任意对象序列化成bytes对象,然后永久存储。
pickle.dump方法可以帮助我们把任意对象序列化成bytes,然后直接写入到文件对象中,不需要我们在一步一步的写入文件,如:

import pickle
class Student:
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender

student1 = Student("小红",15,"女")
with open("student1.data","wb")as f:
    pickle.dump(student1,f)

执行这个例子会生成student1.data,这个文件包含student1对象的信息,用文本编辑器打开这个文件会看到一堆看不懂的内容,这些都是picle保存的对象的信息。

在使用文件时自然也可以把对象从磁盘读取到内存中。我们可以先把内容读取到一个bytes对象中,然后使用pickle.loads方法获取反序列化的对象 例如:

import pickle
class Student:
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender

f = open("student1.data","rb")
data = f.read()
student1 = pickle.loads(data)
f.close()

print("姓名",student1.name)
print("年龄",student1.age)
print("性别",student1.gender)

序列化的时候可以直接写入文件对象,读取的时候当然也可以直接从文件对象中读取 例如:

import pickle
class Student:
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender

with open("student1.data","rb")as f:
    student1 = pickle.load(f)
    print("姓名",student1.name)
    print("年龄",student1.age)
    print("性别",student1.gender)

这个执行结果和手动读取bytes然后使用loads方法反序列化的效果是一样的。

10.4.2 JSON序列与反序列化
json模块的序列化使用方法和pickle模块一模一样,但是pickle可以序列化任意Python对象,而json模块只能序列化10.4.1对应的类型(197页)
使用json模块序列化字典:

import json
student1 = {
    "name":"小明",
    "age":15,
    "gender":"男"
}
print(json.dumps(student1))

注意:json模块会把中文转码为Unicode编码

其他功能和pickle模块一样,参考书本198页

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值