在前二十一天的内容中,所有程序都是在执行后查看输出、返回等等,可是当我们退出程序时,运行的结果都将随之消失,并不能记录写来。
所以,当我们需要记录数据的时候,就可以用创建一个文件来保存它们。
文件的基本内容
- 建立文件
- 基本的读写操作
- 'w' : write写
- 'r' : read读
- 'r+':读写
- 复杂的读写操作
- 一次写入多行
- readline、readlines
- 读取指定字节数的内容
- 在指定位置读取
- 在指定位置写
- 关闭文件的习惯——异常处理
建立文件
我们虽然可以直接手动建立“xxxx.txt”文件,然后再回到程序里调用它,但是,如果能够直接在程序里完成这些操作的话,可以大大节约我们的时间。
在此之前,我们先选择一个保存路径。以本文为例,新建的文件名为“new.txt”,保存路径是F:/Python_Le
- 首先,我们定义我们需要建立的文本路径+名称:
F = 'f:\\Python_Le\\new.txt'
- 然后,我们用open函数建立新的文本文件
new_file = open(F,'w')
这个’w’是以可写方式打开文件,若文件不存在,则建立新文件。除此之外,还有其他的指令:
参数 | 功能 |
‘r’ | 以只读方式打开已存在的文件 |
‘w’ | 以可写方式打开新文件,若文件不存在,则建立新文件 |
‘x’ | 以可写方式建立新文件 |
‘a’ | 追加写入,若文件不存在则建立新文件,再追加写入 |
‘b’ | 二进制模式 |
‘t’ | 文本模式 |
‘+’ | 以读写方式打开 |
‘U’ | 通用换行符模式 |
前四个是打开文件的基本模式,后四者则与前四个相互组合为rb、wb、xb、ab、rt、wt、xt、at、r+、w+、x+、a+等
至于U/doge,我本人用得也特别少,不详细说了。
- 最后,关闭文件
new_file.close()
关闭文件是一个很好的习惯,若打开后执行完不关闭的话,它会一直留在内存,当我们打开的文件过多时,内存就会溢出。
- 接下来,我们再看文件夹里:
有一点要注意的是,我们在写文件路径的时候,为了避免与“\t”、“\a”、“\r”、“\f”等转义字符冲突,我们可以像’f:\Python_Le\new.txt’这样,用双斜杠。
或者是在路径前面加上:“ r ”。比如:
F = r'f:\Python_Le\new.txt'
若无额外的声明,程序中用到的文件一般都是“F:\Python_Le”路径下的“new.txt”
基本的读写操作
‘w’ : write写
使用形式为:f.write(s)。其中,f为文件名,s为要写入的内容。
write方法把s写入f后,会返回写入的字节数:
F = r'f:\Python_Le\new.txt'
new_file = open(F,'w')
W = new_file.write('ksy')
new_file.close()
print('写入%d字节'%(W))
查看结果:
可是,当我们再次用write写入时,
new_file = open(F,'w')
W = new_file.write('again')
print('写入%d字节'%(W))
再打开文件,却发现之前的’ksy’被覆盖掉了
为了避免这样的问题,我们应该用前文提到过的’a’来追加写入:
new_file = open(F,'a')
W = new_file.write('again')
new_file.close()
print('写入%d字节'%(W))
‘r’ : read读
使用形式为:f.read(size)。其中,f为文件名,size为指定读取的字节数,若不写size,则会读取尽可能大的内容:
在刚刚已经记录了“ksyagain”的new.txt文件基础上,读取内容:
new_file = open(F,'r')
R = new_file.read()
print(R)
new_file.close()
ksyagain
若是读取指定的字节:
R = new_file.read(4)
ksya
‘r+’:读写
承接上文,把’r’改成’r+'后,先读再写:
new_file = open(F,'r+')
R = new_file.read()
print(R)
W = new_file.write('K_S_Y')
new_file.close()
print('写入%d'%(W))
- 我们把文件的内容再恢复为“ksyagain”,这次改为先写后读,则会得到另一种结果:
new_file = open(F,'r+')
W = new_file.write('K_S_Y')
R = new_file.read()
print(R)
new_file.close()
print('写入%d'%(W))
我们发现,“K_S_Y”覆盖了之前“ksyag”部分。而读文件的时候,只读取到了“ain”这三个字节的内容。
- 现在,我们再把文件恢复为“ksyagain”,同样是先写后读,只不过在中间加几句话:
new_file = open(F,'r+')
W = new_file.write('K_S_Y')
new_file.close()
print('写入%d'%(W))
new_file = open(F,'r+')
R = new_file.read()
print(R)
new_file.close()
再看输出:
这次就能正常读取内容了。
而刚刚发生只读取部分内容的原因是,后一个动作会在前一个动作结束的字节位置后继续,而不是从文件头开始。
复杂的读写操作
一次写入多行
以写入列表为例:
L = ['1','2','3','D','E','f']
new_file = open(F,'a')
for get in L:
new_file.write(get+'\n')
new_file.close()
我们再次打开new.txt文件
readline、readlines
- readline()可以读取文件的一行
new_file = open(F,'r')
R = new_file.readline()
print(R)
K_S_Yain1
- readlines()则是读取到列表:
new_file = open(F,'r')
L = new_file.readlines()
print(L)
['K_S_Yain1\n', '2\n', '3\n', 'D\n', 'E\n', 'f\n']
读取指定字节数的内容
前文说过,在read(size)中,若不写size的值则尽可能多地读取,若写size,则会读取指定字节的数量:
new_file = open(F,'r')
print( new_file.read(2) )
print( new_file.read(5) )
print( new_file.read(6) )
new_file.close()
K_
S_Yai
n1
2
3
如上,后一个动作会在前一个动作结束的字节位置后继续,而不是从文件头开始。
在指定位置读取
f.seek(offset[,whence])
其中,offset是偏移量,whence是起计位置,默认为0:
new_file = open(F,'r')
new_file.seek(11)
print( new_file.read(1) )
new_file.close()
2
在指定位置写
同样是用seek,这里就不赘述了
关闭文件的习惯——异常处理
在第十六天:异常处理.讲过一种异常处理的一句:
try:
except:
finally:
这种句式的特点是,无论执行了try的内容还是except的内容,最后都将执行finally的内容,所以,我们在写完一些文件的操作以后,可以在finally:中加一句:f.close()。
若是想区分正常打开与错误打开的区别,可以加一个标志位,初值为False,当正常打开时,令其为True。最后再finally语句中判断其真假,作出不同的操作。
比如:
flag = False
try:
new_file = open(F,'r')
print( new_file.readline() )
flag = True
except:
print('打开%s文件错误'%(F))
finally:
if flag:
new_file.close()
print('读取成功,关闭文件')
else:
print('打开%s文件错误'%(F))
执行结果:
————————————————
在今天的内容里,我们发现,除非换行,不然输入的内容全都是堆在一起的字符串,阅读时非常不方便。
如图:
类似这种情况,阅读的时候就很不方便,文字之间夹杂着数字,没有区分,也不便于其他程序的下一步处理。这种情况的处理方式,我们将在下一期介绍另一种保存数据的方法。