为了更好地说明接下来的文件修改操作,我们有必要先来学习下文件操作的常用方法。
一、文件处理中的常用方法
#!/usr/bin/env python3#-*- coding:utf-8 -*-#write by congcong
#flush() 把文件从内存强制刷新到硬盘
f = open('w_flush.txt',mode='r+')
f.write("这是强制刷新到硬盘的文件!")
f.flush()print("查看文件:",f.read())#f.close()
#readable() 判断是否可读
print(f.readable()) #输出:True
f1 = open("w_flush.txt",mode='w') #文件的写操作
f1.write('判断文件是否可读!')
f1.flush()print(f1.readable()) #输出:False (表明写操作时文件也是不可读的)
#readline() 输出一行,碰到\r 或者 \n结束
f = open('w_flush.txt',mode='a',encoding='gbk')
f.write('我是第一行!')
f.write('\n我是第二行!')
f= open('w_flush.txt',mode='r',encoding='gbk')print(f.readline())#输出:我是第一行!
#tell() 返回光标当前位置,以字节为计算单位
print(f.tell()) #输出 ; 14,因为编码为 gbk ,gbk每个中文字符占两个字节,所以此时光标位于第一行末尾
#seek() 将光标移到指定字节位置,以字节为计数单位
print(f.seek(2)) #输出:2
print(f.readline()) #输出;是第一行!
print(f.seek(4)) #输出:4
print(f.readline()) #输出:第一行
#seekable() 判断文件能否seek,linux中使用(一切皆文件)
#read() 括号内指定长度时,就从当前位置开始读几个字符;括号内没有指定长度时,就读全部文件,以字符为单位
print(f.tell())print(f.seek(0))print(f.read(2)) #输出:我是
#truncate() 按指定长度截断文件,括号内指定长度时,就从文件开头开始截断指定长度;不指定长度时,从当前位置到尾部的内容全部去掉#此方法必须是在写模式下使用
f = open('w_flush.txt','r+',encoding='gbk')print(f.seek(4)) #输出;4
print(f.tell()) #输出;4
print(f.truncate(8)) #输出;8
print(f.seek(0)) #输出 :0
f.close()
了解了以上的方法,我们就能愉快地进行文件修改操作了。
二、文件修改操作
当我们以读写(r+)模式打开文件时,,默认会把新增的内容追加到文件最末尾。
这是为什么呢?那我们如果想要修改中间的内容该怎么办呢?
还记得我们刚学过一个tell()方法吗,它的单位是字节,当我们读一段内容的时候,光标会跟着移动,文件读完了,光标就会移到末尾,
再接着写,光标自然会跟着移动,写完后,光标就停留在末尾了,我们可以用tell()方法验证一下猜想,打印此时光标位置,
此时,我们再想读文件内容,就没有任何输出了,都是空白的。这就解释了为何我追加的内容为何无法读出来。
至于为何追加内容会从末尾开始,就容易理解了,当你以追加模式打开文件时,光标会默认移到文件尾部,再开始写。
而文件修改就要用到另一个方法了,seek()方法,它的作用就是移动光标到指定位置,移动的单位是字节,当我们想修改某个地方,
使用seek()方法将光标移到指定位置就可以再修改了,下面我们可以试一下:
#write.txt的原本内容是 :这是第一个我用Python写的文件!#现在我要将‘写’改为‘修改后’
f= open(file='write.txt',mode='r+',encoding='gbk')print('修改前:\n',f.read(),f.tell()) #读出修改前的文件内容,并打印当前光标位置
f.seek(20) #将光标移到第20个字节后的位置(GBK编码一个汉字占2字节,英文占1字节)
f.write('修改后') #写入修改内容
f.seek(0) #将光标移到文件开头
print(f.tell()) #打印当前光标位置
print('修改后:\n',f.read(),f.tell()) #读出修改后的文件内容,并打印当前光标位置
f.close()#关闭文件
'''这是第一个我用Python写的文件! 29
0
修改后:
这是第一个我用Python修改后件! 29'''
没有报错,正常执行,‘写’ 也的确被改成了 ‘修改后’ ,文件大小也并未改变,但是也有我们不想修改的内容被覆盖了,这就尴尬了。。。
原因在这里:
这是硬盘的存储原理导致的,当你把文件存到硬盘上,就在硬盘上划了一块空间,存数据,等你下次打开这个文件 ,seek到一个位置,每改一个字,就是把原来的覆盖掉,如果要插入,是不可能的,因为后面的数据在硬盘上不会整体向后移。所以就出现 当前这个情况 ,你想插入,却变成了会把旧内容覆盖掉。
解决方法呢?
想修改当然可以,但是不要在硬盘上修改,把内容全部读到内存里,数据在内存里可以随便增删改查,修改之后,把内容再全部写回硬盘,把原来的数据全部覆盖掉。
例如:
#-*- coding:utf-8 -*-
import os #导入模块
f1= 'notebook.txt' #待修改的文件
f2 = 'note_new.txt' #修改后的文件
f_old = open(f1,mode='r',encoding='utf-8') #打开待修改的文件
f_new = open(f2,mode='w',encoding='utf-8') #写入修改的文件
old_str= '一' #待修改的字符串
new_str = 'one' #修改后的字符串
count = 0 #统计修改次数
for line in f_old: #循环读
if old_str inline:
newline= line.replace('一','one') #替换
count += 1 #每修改一次自增1
else:
newline=line
f_new.write(newline)#写入修改后的文件
f_old.close() #依次关闭
f_new.close()
os.replace('note_new.txt','notebook.txt') #用新文件里的内容替换旧文件
print('修改次数:'count) #修改次数:5