第七章 文件-1
7.1 文件的相关概念
7.2 文件的使用
7.3 文件的读/写操作
7.4 文件和目录操作
7.5 CSV文件格式读/写操作
7.6 JSON文件的操作(自学)
7.7 pydoc文件操作(自学)
知识导入
- 在前面的章节中我们使用的原始数据很多都是通过键盘输入的,并将输入的数据放入指定的变量中,若要处理(计算、修改、删除等)这些处据,可以从指定的变量中取出并进行处理。
- 但是在数据量大,数据访问频繁以及数据处理结果需要反复查看或使用时,就有必要将程序的运行结果保存下来。
- 为了解决以上问题,Python引入了文件,将这些待处理的数据存储在指定的文件中,当需要处理文件中的数据时,可以通过文件处理函数,取得文件内的数据并存放到指定的变量中进行处理,数据处理完毕后再将数据存回到指定的文件中。
- 有了对文件的处理,不但数据容易维护,而且同一个程序可处理数据格式相同但文件名不同的文件,增加了程序的使用弹性。
7.1 文件的相关概念
文件
- 文件是数据的集合和抽象,以文本、图像、音频、视频等形式存储在计算机的外部存储介质上
- 根据文件的存储格式不同,可以分为:文本文件和二进制文件
1 文本文件
文本文件
- 文本文件是由字符组成,这些字符可以按ANSI、UTF-8或者Unicode等格式编码
- 文本文件可看作是存储在磁盘上的长字符串,例如一个txt格式的文本文件
- 文本文件的内容便于查看和编辑,存取时需要编解码,要花费一定的转换时间。
- 大部分文本文件都可以通过文本编辑软件或文字处理软件创建、修改和读取,如常见的软件是记事本、UltraEdit等。
2 二进制文件
二进制文件
- 二进制文件存储的是由0和1组成的二进制,没有统一的字符编码,只能当作字节流,而不能看作是字符串
- 二进制文件内部数据的组织格式与文件用途有关
- 例如png格式的图片文件,avi格式的视频文件
3 文本文件与二进制文件的区别
【微实例】 理解文本文件和二进制文件的区别
用文本编辑器生成一个包含“中国是个伟大的国家!”的txt格式文本文件,命名为7-1.txt
分别用文本文件和二进制文件方式读入 ,并打印输出效果
tFile=open("7-0.txt","rt")
print(tFile.readline())
tFile.close()
bFile=open("7-0.txt","rb")
print(bFile.readline())
bFile.close()
运行结果
中国是个伟大的国家!
b'\xd6\xd0\xb9\xfa\xca\xc7\xb8\xf6\xce\xb0\xb4\xf3\xb5\xc4\xb9\xfa\xbc\xd2\xa3\xa1'
【可以看到,采用文本方式读入文件,文件经过编码形成字符串,打印出有含义的字符;采用二进制方式打开文件,文件被解析为字节(Byte)流】
4 文件指针
文件指针
- 文件指针是文件操作的重要概念, Python用文件指针表示当前读/写位置。在文件读/写过程中,文件指针的位置是自动移动的。
- 以只读方式打开文件时,文件指针指向文件开头,向文件中写数据或追加数据时,指针指向文件末尾。通过设置文件指针的位置,可以实现文件的定位读写。
tFile=open("7-0.txt","rt")
print(tFile.readline())
tFile.close()
bFile=open("7-0.txt","rb")
print(bFile.readline())
bFile.close()
7.2 文件的打开与关闭
文件
- Python对文本文件和二进制文件采用统一的操作步骤,即“打开-操作-关闭”
- 首先将文件“打开”指,使得当前程序有权操作这个文件
- 打开后的文件处于占用状态,此时,另一个进程不能操作这个文件。可以通过一组方法读取文件的内容或向文件写入内容。此时,文件作为一个数据对象存在,采用
<a>.<b>()
方式进行操作 - 操作之后需 要将文件关闭,关闭将释放对文件的控制使文件恢复存储状态
open()函数
- Python用内置的 open()函数打开文件,并创建一个文件对象。或者说返回一个操作这个文件的变量。
- 格式:
<文件对象>=open(<文件名>[,<打开方式>])
- <文件名>可以是包含文件名的完整路径(如 "d:\abc\7-1.txt")。如果只有文件名("7-1.txt"),没有带路径的话,那么Python会在当前文件夹中去找到该文件并打开
- <打开方式>用于控制使用何种方式打开文件
f=open("c:\\text\\score.txt","r")
f=open("c:/text/score.txt","r")
打开模式 | 含义 |
---|---|
"rt"或"r" | 只读打开文本文件,只允许读数据 |
"wt"或"w" | 只写打开或建立一个文本文件,只允许写数据 |
"at"或"a" | 追加打开一个文本文件,并在文件末尾写数据 |
"rb" | 只读打开一个二进制文件,并允许读数据 |
"wb" | 只写打开或建立一个二进制文件,只允许写数据 |
"ab" | 追加打开一个二进制文件,并在文件末尾写数据 |
注:'r','w','a'可以和'b','t','+'组合使用,形成既表达读写又表达文件模式的方式
打开模式 | 含义 |
---|---|
"rt+"或"r+" | 读写打开一个文本文件,允许读和写 |
"wt+"或"w+" | 读写打开或建立一个文本文件,允许读和写 |
"at+"或"a+" | 读写打开一个文本文件,允许读,或在文件末尾追加数据 |
"rb+" | 读写打开一个二进制文件,允许读和写 |
"wb+" | 读写打开或建立一个二进制文件,允许读和写 |
"ab+" | 读写打开一个二进制文件,允许读,或在文件末尾追加数据 |
打开文件常用组合
#以文本方式只读打开一个文件,读入后不能对文件进行修改
f=open("c:\\text\\score.txt","r")或 f=open("c:\\text\\score.txt","r")
#以文本方式可读写地打开一个文件,可以读入并修改文件
f=open("c:\\text\\score.txt","r+")
#以文本方式打开一个文件,准备覆盖写入一批内容,并保存为新文件
f=open("c:\\text\\score.txt","w")
#以文本方式打开一个空文件或已有文件,追加形式写入一批内容,更新原文件
f=open("c:\\text\\score.txt","a+")
#以二进制方式只读打开一个文件,读入后不能对文件进行修改
f=open("c:\\text\\score.txt","rb")
close()方法
- 文件使用结束后要用close()方法关闭,以防止其被误操作而造成文件信息的破坏和文件信息的丢失
- 格式:
<文件对象>.close()
- 通常情况下,Python 操作文件时,使用内存缓冲区缓存文件数据。关闭文件时,Python 将缓存的数据写入文件,然后关闭文件,释放对文件的引用
- 关闭文件是断开文件对象与文件之间的关联,此后不能再继续通过该文件对象对该文件进行读写操作
【例7-1】 新建一个文本文件a.txt,其内容为"千里之行,始于足下",保存在"D:\python"。编写 程序,打开该文件,向其中追加内容“温故而知新”,然后读取该文件内容,并关闭该文件
#E7-1.py
f=open("d:\\python\\a.txt","a+")#打开文件,创建文建对象f,以追加写方式向其写入内容
f.write("\n温故而知新") #向文件对象f追加写入"换行"及"温故而知新"
f.seek(0,0) #将文件指针定位到文件对象f开头
print(f.readline()) #输出该文件对象f第一行内容
print(f.readline()) #输出该文件对象f第二行内容
f.close()
7.3 文件读写
文件读
- 当文件被打开后,根据文件的访问模式可以对文件进行读操作
- 根据打开方式不同,读文件的方式也会不同
- 如果文件是以文本文件方式打开的,默认情况下,程序按照当前操作系统的编码方式来读文件,也可以指定编码方式来读文件
- 如果文件是以二进制文件方式打开的,则按字节流方式读
- 文件对象提供了三种读取方法:read()、readline()和readlines()
文件读——read()
- 格式:
f.read([size])
- f为文件对象,表示从文件中读入整个文件内容,也就是说读取到文件结束为止。如果有参数size,表示读入前size长度的字符串或字节流
- 如果文件不大,可以一次性将文件内容读入,保存到程序内部变量中
- f.read()返回的结果是一个字符串
>>> f=open("d:/python/a.txt","r")
>>> s=f.read()
>>> print(s)
千里之行,始于足下
温故而知新
>>> f.close()
>>> f=open("d:/python/a.txt","r")
>>> s=f.read(9)
>>> print(s)
千里之行,始于足下
>>> f.close()
文件读——readline()
- 格式:
f.readline([size])
- f为文件对象,表示从文件中读取一 行内容。如果有参数size,表示读入该行前size长度的字符串或字节流
- f.readline()返回的结果是一个字符串
- 如果当前处于文件末尾,则返回空串
>>> f=open("d:/python/a.txt","r")
>>> s=f.readline()
>>> print(s)
千里之行,始于足下
>>> s=f.readline()
>>> print(s)
温故而知新
>>> f.close()
>>> f=open("d:/python/a.txt","r")
>>> s=f.readline(4)
>>> print(s)
千里之行
>>> s=f.readline(4)
>>> print(s)
,始于足
>>> f.close()
文件读——readlines()
- 格式:
f.readlines([hint])
- 从文件中读入所有行,以每行为元素形成一个列表
- 如果有参数hint,表示从当前读写位置开始需要以行为单位至少读出的字符数或字节数
- 如果当前文件指针处于文件末尾,则返回空列表
>>> f=open("d:/python/a.txt","r")
>>> ls=f.readlines()
>>> print(ls)
['千里之行,始于足下\n', '温故而知新']
>>> ls=f.readlines()
>>> print(ls)
[ ]
>>> f.close()
>>> f=open("d:/python/a.txt","r")
>>> ls=f.readlines(4)
>>> print(ls)
['千里之行,始于足下\n']
>>> ls=f.readlines(4)
>>> print(ls)
['温故而知新\n']
>>> f.close()
文件读——遍历文件
- 从文本文件中逐行读入内容并进行处理是一个基本的文件操作需求
- 文本文件可以看作是由行组成的组合类型
- 因此,可以使用循环遍历文件
f=open(<文件路径及名称>,"r")
for <变量名> in f:
#处理一行数据
f.close()
f=open("d:/python/a.txt","r")
for line in f:
print(line)
f.close()
运行结果
千里之行,始于足下
温故而知新
文件写——write()
- 格式:
f.write(s)
- 向文件写入一个字符串s或字节流s,并可返回写入的字符个数或字节流。每次写入后,将会记录一个写入指针
- 该方法可以反复调用,在写入指针后分批写入内容,直至文件被关闭
- 要显式地使用'\n'对写入文本进行分行,如果不进行分行,每次写入的字符串会被连接起来
f=open("d:/python/b.txt","w")
f.write("《凉州词》\n")
f.write("唐·王之涣\n")
f.write("黄河远上白云间,一片孤城万仞山。\n")
f.write("羌笛何须怨杨柳,春风不度玉门关。\n")
f.close()
>>> f=open("d:/python/b.txt","w")
>>> f.write("《凉州词》\n")
6
>>> f.close()
文件写——writelines()
- 格式:
f.writelines(<元素为字符串的列表>)
- 在文件的当前位置将列表中的所有元素写入文件
- 如需换行,则需在列表中添加换行符
\n
元 素
f=open("d:/python/c.txt","w")
ls=["《凉州词》\n","唐·王之涣\n","黄河远上白云间,一片孤城万仞山。\n",\
"羌笛何须怨杨柳,春风不度玉门关。\n"]
f.writelines(ls)
f.close()
【例7-2】 把一个包含两列内容的文件input.txt(如图所示),分割成两个文件col1.txt和col2.txt,每个文件有一列内容。
input.txt - -记事本
file1 file2
Python Java
C# VB
Go VC++
def split_file(filename): #函数,把文件分成两列
col1=[]
col2=[]
fd=open(filename)#以读模式打开文件input.txt,创建文件对象fd
text=fd.read() #读取文件对象全部内容返回一个字串符
lines=text.splitlines()#以行为单位分割文本,返回列表lines
for line in lines: #遍历列表lines
part=line.split() #将每一行的元素进行分割
col1.append(part[0])
col2.append(part[1])
return col1,col2
def write_list(filename,alist): #把列表内容写入文件
fd=open(filename,”w”)
for line in alist:
fd.write(line+’\n’)
filename=’d:/python/input.txt’
col1,col2=split_file(filename)
write_list(‘d:/python/col1.txt’,col1)
write_list(‘d:/python/col2.txt’,col2)
col1=[ "File1","Python","C#","Go"]
col2=["File2","Java","VB","VC++"]
lines:['file1\tfile2', 'Python\tJava', 'C#\tVB', 'Go\tVC++']
特殊:
- 前面介绍的读写方法都是读写字符串,对于其他类型数据则需要转换
- 可使用Python标准库pickle库中的
dump()
和load()
方法实现二进制文件中其他类
型数据对象的读写 -
pickle.dump(<数据>,<文件对象>)
表示直接把其他类型的对象转换为字符串并存入文件中 -
pickle.load(<文件对象>)
表示从二进制文件中读取字符串,并将字符串转换为Python的数据对象,该方法返回还原后的字符串
>>> import pickle
>>> x=100
>>> f=open ("d:/python/b.txt","wb+")
>>> pickle.dump(x,f)
>>> f.seek(0)
0
>>> x=pickle.load(f)
>>> x
100
>>> f.close()
文件的定位
- Python在实际应用中,如果需要读取某个位置的数据,或向某个位置写入数据,需要定位文件的读/写位置,包括获取文件的当前位置,以及定位到文件的指定位置
- 文件指针定位的方法有
tell()
和seek()
文件的定位——tell ()
- 格式:
f.tell()
- 返回文件的当前读写位置
>>> f=open("d:/python/col1.txt","r")
>>> f.tell()
0
>>> f.read(5)
'file1'
>>> f.read(4)
'\nPyt'
>>> f.tell()
10
>>> f.close()
文件的定位——seek()
- 格式:
f.seek(offset,whence)
- 把文件指针移动到相对于whence的offset位置
- whence指定移动的基准位置,默认值为0
0:以文件开始位置作为基准点
1:以当前位置为基准点
2:以文件末尾为基准点 - offset表示要移动的字节数,offset为正数表示向文件末尾方向移动,offset为负数表示向文件开头方向移动
>>> f=open("d:/python/col1.txt","rb")
>>> f.seek(0)
0
>>> f.read(2)
b'fi'
>>> f.seek(1,1)
3
>>> f.read(2)
b'e1'
>>> f.seek(2)
2
>>> f.read(1)
b'l'
>>> f.seek(0,2)
23
对于文本文件,f.seek(offset,whence),当whence参数为1或2时,offset参数必须为0
>>> f.close()
>>> f=open("d:/python/col1.txt","r")
>>> f.seek(0)
0
>>> f.read(2)
'fi'
>>> f.seek(1,1)
Traceback (most recent call last):
File "<pyshell#19>", line 1, in
<module>
f.seek(1,1)
io.UnsupportedOperation: can't do
nonzero cur-relative seeks