在前面我们学习了变量、序列、对象,在他们中存储的数据是暂时的,程序结束数据就会丢失。为了能够长时间保存数据,需要将数据保存到磁盘文件。
本篇博客就来介绍如何对磁盘数据进行读写等操作。

1. 数据读取理论

在python中要想读取数据,需要先将磁盘文件打开,建立数据传输的通道。

1.1 打开文件

打开文件使用open函数,open函数基本语法格式如下:

file =open(filenam,mode = 'r',buffering = -1, encoding = NOne,errors = None, closefd = True, opener = NOne)

open函数用于打开文件并返回流,当打开失败时会出现OSError错误。

主要用到的参数:

1)filename: 文件名称
(1) 文件可以是文本文件或二进制文件
(2)文件名称需要使用单引号或者双引号括起来
(3)引号内部有3种情况:
    a. 要打开的文件和当前文件在同一目录下:  可以使用相对路径。
    b. 要打开的文件与当前文件不在同一目录下,必须使用完整的绝对路径
    c. 还可以使用文件描述符。(我还不清楚)
2)mode: 文件的打开模式

取值

说明

指针位置

r

以只读方式打开文件

文件开头

r+

打开文件后,可以读取文件内容,也可以写入新的内容覆盖原有内容

文件开头

rb+

以二进制方式打开文件,且采用读取的方式

文件开头

w

以只写方式打开文件

文件开头

w+

打开文件后,先清空原有内容,对空文件进行写入

文件开头

wb+

以二进制方式打开文件,且采用写入的方式

文件开头

a

以追加方式打开文件,

文件结尾

w+

打开文件后,先清空原有内容,对空文件进行写入

文件结尾

wb+

以二进制方式打开文件,且采用写入的方式

文件结尾

1.2 读取文件

1.2.1 调用read方法读取

read函数从open函数返回的流中解码数据并返回结果

file.read(size = -1)

参数含义:

1) size: 可选参数,指定要读取的字符个数,read采取的是贪婪读取模式,默认值表示读取全部。size的设定可以在面对大文件时,
避免一次性读取过多内容,可以按照需求设置读取长度。
注意:read方法读取文件时,是从文件的开头开始读取的,读取完毕指针移到文件末尾。

1.3 写入文件

python对象提供了write()方法,可以向文件中写入内容,语法格式如下:

file.write(string)

1.4 关闭文件

打开文件后,需要及时关闭,忘记关闭文件会造成系统资源消耗,且会影响后续文件的访问。文件关闭使用文件对象的close方法实现。语法格式如下:

file.close()

2. 演练

2.1 读取文件

2.1.1 mode = 'r’与mode='r+'模式

使用非二进制的mode = 'r’与mode='r+'模式读取文件

原文件是这样的

Python 中如何读 在 数据 python数据读入_文件指针

接下来,先演练读取数据,读取数据后要及时调用file.close关闭

以mode = 'r' 或者mode = 'r+'的打开文件结果如下:

Python 中如何读 在 数据 python数据读入_读取文件_02

Python 中如何读 在 数据 python数据读入_Python 中如何读 在 数据_03

以mode = 'r' 或者mode = 'r+'的方式读取文件:

Python 中如何读 在 数据 python数据读入_读取文件_04

Python 中如何读 在 数据 python数据读入_Python 中如何读 在 数据_05

mode = 'r+' 模式,不仅可以使用read方法读取文件,而且也可以使用write方法写入新的内容。而mode = 'r' 模式为只读模式,不能使用write方法

Python 中如何读 在 数据 python数据读入_读取文件_06

Python 中如何读 在 数据 python数据读入_Python 中如何读 在 数据_07


Python 中如何读 在 数据 python数据读入_文件指针_08

可以看到,mode ='r+'模式,不仅可以读取数据,而且支持写入数据。但是要注意,当打开文件之后,第一次调用read()方法读取文件后,
指针在从开头移动到了文件末尾,这时再执行write()方法会在此时指针的位置往后继续写入,而写入之后文件指针在添加了写入内容的
整个文件的末尾,因此再调用read()函数时,并不能读取到文件内容。

当先写入后读取文件,来看下运行情况:

Python 中如何读 在 数据 python数据读入_读取文件_09


Python 中如何读 在 数据 python数据读入_Python 中如何读 在 数据_10

这个文件的运行如下:首先打开文件,指针此时在文件开头,然后调用write()方法,会从指针的位置向后写入write()中的内容:
已存在文件的r+模式打开;此时指针移动到“开”字后面,而原文件中的“相对人类的欲望而言,资”这几个字符被替换为长度相等的
“已存在文件的r+模式打开”(write()方法中应该1个汉字占据两个字符),因此下面调用read()方法时,指针从“开”字后面的“源”开始,
输出:源是稀缺的!!!
总结:
1)以text mode 形式打开的文件返回TextIOWrapper。
2)open()函数建立了磁盘数据传输的通道,返回流对象。
3)open()函数执行后,文件指针位于文件开头
4)read()函数以贪婪模式执行,默认读取全部文件数据
5)read()函数执行后,文件指针位于文件末尾

2.1.2 以二进制方式打开文件

mode = 'rb’或mode=‘rb+’
同理mode = 'rb’模式是只读模式,无法进行write()方法的写入操作

Python 中如何读 在 数据 python数据读入_Python 中如何读 在 数据_11

mode = 'rb+'模式,不仅可以读取文件,而且可以写入文件,但是写入内容必须为字节对象。这里使用

bytes函数转换。

Python 中如何读 在 数据 python数据读入_文件指针_12


Python 中如何读 在 数据 python数据读入_大数据_13

2.2 以写模式打开文件

2.2.1 以只写模式打开文件

以只写模式mode = 'w’或者mode = 'wb’模式打开文件,只能进行write()方法的操作,不能进行read()方法操作。

Python 中如何读 在 数据 python数据读入_Python 中如何读 在 数据_14


以只写模式,若原文件存在,会先清空原文件内容,再进行写入。

Python 中如何读 在 数据 python数据读入_Python 中如何读 在 数据_15


Python 中如何读 在 数据 python数据读入_打开文件_16


Python 中如何读 在 数据 python数据读入_大数据_17


Python 中如何读 在 数据 python数据读入_Python 中如何读 在 数据_18


Python 中如何读 在 数据 python数据读入_读取文件_19

2.2.2 以读写方式打开文件

Python 中如何读 在 数据 python数据读入_大数据_20


Python 中如何读 在 数据 python数据读入_Python 中如何读 在 数据_21


Python 中如何读 在 数据 python数据读入_文件指针_22


Python 中如何读 在 数据 python数据读入_读取文件_23

总结:
1) mode = 'w' 或mode = 'wb'模式为只写模式,不能使用read()方法
2)mode = 'w+'或mode='wb+'模式为读写模式,可以使用read()方法;但是可以看到read()的内容为空,
这是因为'w'的相关模式在打开文件后,会先清空原有内容,使其转变为空的文件,因此,
第一次的read()方法输出为空,写入内容后,文件指针在文件末尾,因此,第二次的read()方法输出为空。

2.3 以追加模式打开文件

2.3.1 以追加模式打开文件

Python 中如何读 在 数据 python数据读入_文件指针_24


Python 中如何读 在 数据 python数据读入_大数据_25


可以看到以mode = 'a’或者mode = 'ab’追加模式打开文件是不能读取文件内容的。

ecomi = open('C:\\Users\\changyanhua\\Desktop\\testw.txt', mode='a')
print(ecomi)
# print(ecomi.read())
# print('*'*20)
ecomi.write('花好月圆')
# ecomi.write(bytes('基本文件操作', 'utf-8'))
# print(ecomi.read())
ecomi.close()

Python 中如何读 在 数据 python数据读入_大数据_26

# 相对人类的欲望而言,资源是稀缺的!!!
ecomi = open('C:\\Users\\changyanhua\\Desktop\\testw.txt', mode='ab')
print(ecomi)
# print(ecomi.read())
# print('*'*20)
# ecomi.write('花好月圆')
ecomi.write(('二进制'.encode()))
# print(ecomi.read())
ecomi.close()

Python 中如何读 在 数据 python数据读入_Python 中如何读 在 数据_27

总结:
1)以追加模式打开的文件不能进行读取操作
2)文件打开后,文件指针放在文件末尾,新内容写入已有内容之后。

2.3.2 以读写模式打开

Python 中如何读 在 数据 python数据读入_Python 中如何读 在 数据_28


![在这里插入图片描述](https://img-blog.csdnimg.cn/c28c8b81fad44caa899cf498faa8f49e.png

Python 中如何读 在 数据 python数据读入_大数据_29


Python 中如何读 在 数据 python数据读入_大数据_30

总结:
1)采用mode = 'a'或者mode='ab'无法调用read()方法
2)采用mode = 'a+'或者mode='ab+'可以调用read()方法,但是同前面一样的道理,文件指针在文件末尾,所以没有读取到数据。
下面来看以二进制方式打开文件,结果根据mode模式不同而不同:
以mode = 'rb',只读二进制格式打开,返回BufferedReader

Python 中如何读 在 数据 python数据读入_Python 中如何读 在 数据_31

以mode = 'wb',采用只写;或者mode = 'ab'追加模式二进制格式打开,返回BufferedWriter

Python 中如何读 在 数据 python数据读入_文件指针_32


Python 中如何读 在 数据 python数据读入_打开文件_33

以mode = 'rb+',或者mode = 'wb+'或者mode = 'ab+'读写模式二进制格式打开,返回BufferedRandom

Python 中如何读 在 数据 python数据读入_文件指针_34


Python 中如何读 在 数据 python数据读入_读取文件_35


Python 中如何读 在 数据 python数据读入_文件指针_36

3. 读取文件

3.1 read()方法

read函数从open函数返回的流中解码数据并返回结果

file.read(size = -1)

参数含义:

1) size: 可选参数,指定要读取的字符个数,read采取的是贪婪读取模式,默认值表示读取全部。size的设定可以在面对大文件时,
避免一次性读取过多内容,可以按照需求设置读取长度。
注意:read方法读取文件时,是从文件的开头开始读取的,读取完毕指针移到文件末尾。

Python 中如何读 在 数据 python数据读入_打开文件_37

1)结合前面代码可以看到,read()函数默认读取全部字符
2)还可以通过size指定读取字符的个数:1个汉字算一个字符。

3.2 read.line()方法

当文件很大,一次性读取全部内容,容易造成内存不足,可以逐行读取,采用read.line()方法

Python 中如何读 在 数据 python数据读入_文件指针_38

Python 中如何读 在 数据 python数据读入_文件指针_39


还可以使用readline逐行读取全部内容,判断依据以读取内容是否为空来判断:

Python 中如何读 在 数据 python数据读入_Python 中如何读 在 数据_40

# 相对人类的欲望而言,资源是稀缺的!!!
ecomi = open('C:\\Users\\changyanhua\\Desktop\\ec_test.txt', mode='r')
print(ecomi)
i = 0

while True:
    line_con = ecomi.readline()
    print(line_con)
    if line_con == '\n':
        i += 1
        print(i)
    if line_con == '':
        break
ecomi.close()

Python 中如何读 在 数据 python数据读入_打开文件_41


Python 中如何读 在 数据 python数据读入_文件指针_42

1)中间中间的空白部分读取内容是换行符'\n',并不是空,所以有空白也不影响读取至文件结束。
2)输出代码中line_con的类型,显示为str;因此readline的返回结果为字符串。

Python 中如何读 在 数据 python数据读入_打开文件_43

3.3 readlines()方法

Python 中如何读 在 数据 python数据读入_文件指针_44


Python 中如何读 在 数据 python数据读入_读取文件_45

从代码运行结果可以看出:
1) readlines读取全部文件内容;
2)readlines的返回结果为字符串列表,列表的每个元素记录一行内容;
3)返回内容不仅包括文本内容,还包括每行的换行符: \n;

对于结果列表,使用for循环遍历,可以得到与read()方法一样的结果

ecomi = open('C:\\Users\\changyanhua\\Desktop\\ec_test.txt', mode='r')
print(ecomi)

lin_cons = ecomi.readlines()
for item in lin_cons:
    print(item)

Python 中如何读 在 数据 python数据读入_打开文件_46


Python 中如何读 在 数据 python数据读入_大数据_47

4. 文件指针

4.1 移动文件指针:seek()

前面在读写函数时,经常发生文件指针在文件结尾,导致读取内容为空的情况,如果想要得到内容或者想要读取部分内容,可以移动文件指针的位置,使用seek()方法

file.seek(offset[,whence])

参数含义:

1) offset: 移动的字符个数,seek()方法中,汉字占两个字符
2)whence: 指定从什么位置开始计算。
(1)0: 从文件头开始
(2)1:从当前位置开始
(3)2: 从文件末尾开始

不指定移动字符的个数,默认移动整个文件字符的长度:

# 相对人类的欲望而言,资源是稀缺的!!!
ecomi = open('C:\\Users\\changyanhua\\Desktop\\testw.txt', mode='r+')
print(ecomi)

cons = ecomi.read()
print(cons)
print('*'*20)
ecomi.write('\n移动文件指针')
# 未人为移动指针时:
pre_cons = ecomi.read()
print(pre_cons)
print('*'*20)
ecomi.seek(0)
# 主动移动指针后:
aft_cons = ecomi.read()
print(aft_cons)

Python 中如何读 在 数据 python数据读入_读取文件_48


指定移动字符的长度(汉字及其符号,占两个字符长度)

# 相对人类的欲望而言,资源是稀缺的!!!
ecomi = open('C:\\Users\\changyanhua\\Desktop\\testw.txt', mode='r+')
print(ecomi)

cons = ecomi.read()
print(cons)

count = 2* len(cons)
print(count)

print('*'*20)
ecomi.write('\n移动文件指针')
# 未人为移动指针时:
pre_cons = ecomi.read()
print(pre_cons)

print('*'*20)
ecomi.seek(count, 0)
# 主动移动指针后:
aft_cons = ecomi.read()
print(aft_cons)

Python 中如何读 在 数据 python数据读入_读取文件_49

如果文件不是使用二进制方式打开是只能从文件开头开始计算,即:whence取值只能为0,否则会出现异常:

Python 中如何读 在 数据 python数据读入_大数据_50

4.2 返回文件指针位置:tell()

Python 中如何读 在 数据 python数据读入_读取文件_51


Python 中如何读 在 数据 python数据读入_文件指针_52

关键点:
1)打开文件后文件指针位置在开头0
2)一个汉字占两个字符
3)每行结尾的换行符'\n'占两个字符