文件操作
基本的文件处理
什么是文件
操作系统提供给用户的一个虚拟单位
文件有什么用
存储数据
打开文件的流程
找到文件路径
path = r'xxx\xxx.py' # 鼠标右键点击文件,copy path
双击打开
f = open(path, 'w') # r-->read 只读 ; w-->只写,清空当前文件后写入
print(f) # 文件数据类型
看文件
data = f.read()
print(data)
写文件
f.write('nick handsome')
关闭文件
# del f # 只删除了文件的引用以及文件在python内存中的占用,但是没有删除对操作系统的占用
f.close() # 关闭操作系统对文件的占用
文件的三种打开方式
只读(r)
用f.read()来执行
将文件内容拿出来,读一行少一行
也就是说在同一次运行中,先执行f.read()之后,如果再执行一次,则第二次会什么都读不出来
这个时候,就要使用readline来一行一行的读
先创建一个TXT文件,内容为:
这是一个txt文件
这是第二行
f = open('test.py','r',encoding='utf8') # 只读 # 文件内容拿出来,读一行少一行
print(f.read()) # 读取文件所有内容
print(1,f.readline()) # 已被读完,无法再次读取
print(2,f.readline()) #
结果为:
这是一个txt文件
这是第二行
1
2
f = open('test.txt','r',encoding='utf8')
print(1,f.readline())
print(2,f.readline())
结果为:
1 这是一个txt文件
2 这是第二行
蚁后使用这个方式来循环文件:
f = open('test.txt','r',encoding='utf8')
for i in f:
print(i)
print(f.readable()) # 是否可读
f.close()
结果为:
这是一个txt文件
这是第二行
True
只写(w)
在打开一个文件后,会将文件内容清空再写
用f.write()来表示
f = open('test.py','w',encoding='utf8') # 只写 # 清空后再写
lt = ['sdklfj','sdkfjksldf']
res = '\n'.join(lt)
f.write(res)
print(f.readable())
print(f.writable())
f.writelines(['sdklfj','sdkfjksldf'])
f.close()
结果为:
False
True
可见只写里是无法读取的。
同时在text.py文件的内容变成了:
sdklfj
sdkfjksldfsdklfjsdkfjksldf
追加(a)
追加就和append一样,顾名思义,在文件的末尾添加上想添加的东西
用的也是f.write()
f = open('test.py','a',encoding='utf8') # 追加 # 文件末追加
f.write('写的是什么东西啊')
f.close()
test.py结果变为:
sdklfj
sdkfjksldfsdklfjsdkfjksldf写的是什么东西啊
with管理文件上下文
之前我们使用open()方法操作文件,但是open打开文件后我们还需要手动释放文件对操作系统的占用。但是其实我们可以更方便的打开文件,即Python提供的上下文管理工具——with open()
ith open('text.txt', 'rt', encoding='utf8') as f:
print(f.read())
结果为:
这是一个txt文件
这是第二行
with open()方法不仅提供自动释放操作系统占用的方法,并且with open可以使用逗号分隔,一次性打开多个文件,实现文件的快速拷贝
with open('text.txt', 'rb') as fr, \
open('text.py', 'wb') as fw:
f.write(f.read())
在这里使用\时,虽然换行了,但是在Python中默认他还是同一行,这样操作和在同一行没什么分别,但是对于看这段代码的人来说,能更加清楚的知道了打开了几个文件,分别是什么
文件的高级应用
文件高级应用可以做到即可读又可写(尽量不要使用)
r+
r+的写入是在原本文件后面追加
# test.py 文件内容为 '''111'''
with open('test.py', 'r+', encoding='utf8') as fr:
data = fr.read()
print(fr.writable())
fr.write('x = 10')
print(data)
结果为:
True
'''111'''
文件内容变为'''111'''x = 10
注意此时打印的data没有x = 10 是因为在写之前就已经读取了
w+
清空文件的功能是W提供的,w+更不要使用
也就是说,f.write()并不是清空文件的罪魁祸首
with open('test.py', 'w+', encoding='utf8') as fr:
print(fr.readable())
fr.write('x = 10')
文件结果变为x = 10
with open('test.py', 'w+', encoding='utf8') as fr:
# print(fr.readable())
# fr.write('x = 10')
data = fr.read()
print(data)
此时文件结果反而什么也没有,并不是不能用read,而是此时文件里已经什么也没有了。如果要问为什么,就是被w清空了
a+
a+则是在原本追加的情况下还能进行读取
with open('test.py', 'a+', encoding='utf8') as fr:
data = fr.read()
print(data)
fr.write('x = 10')
fr.flush()
这个时候你就会发现,依旧是什么都没有打印,但是寻思a也没有清除文本内容呀?而且多次打印后发现,txt文件中的x越来越多,但是却什么都打印不出来。这里就涉及到了一个指针的问题,我会在接下来一一进行阐述
指针
指针是文件的内置方法,其实也就是当你鼠标点击某一行字的时候,那一闪一闪的竖就是指针。那么问题回到上面,为什么明明文本中有数据,但是read()却读不出来呢?这就是因为read函数是从指针的地方开始读,而a+默认指针是在文件的末尾,所以自然什么也读不出来了。之前说的只读模式里一次运行只能读取一次也是相同的道理。
seek
用于改变指针位置后读取
with open('test.py', 'rb') as fr:
fr.seek(1) # 1表示位移1位,默认从文件头开始
fr.seek(1, 0) # 1表示偏移1位,0表示从头开始(这里和第一个一样)
fr.seek(2, 1) # 1表示偏移1位,1表示从当前位置开始
fr.seek(0, 2) # 0表示偏移0位,2表示文件末开始,把指针移到文件末
print(fr.read())
结果依次为:
b' = 10x = 10x = 10x = 10x = 10x = 10x = 10x = 10x = 10x = 10'
b' = 10x = 10x = 10x = 10x = 10x = 10x = 10x = 10x = 10x = 10'
b' 10x = 10x = 10x = 10x = 10x = 10x = 10x = 10x = 10x = 10'
b''
因此在配合seek之后,a+也可以读取文件了
with open('test.py', 'a+', encoding='utf8') as fr:
fr.seek(1, 0)
data = fr.read()
print(data)
fr.write('x = 10')
fr.flush()
tell
同于告诉你指针的位置
with open('test.py', 'r', encoding='utf8') as fr:
fr.seek(2, 0)
print(fr.tell()) # 2
read(n)
可以读取文件中的字节
with open('test.py', 'r', encoding='utf8') as fr:
print(fr.read(5)) # x = 1
print(fr.read(6)) # x = 10
truncate截断
只读模式无法使用。只写模式会清空文件,所以一般用于追加模式
with open('test.py', 'a', encoding='utf8') as fr:
fr.truncate(2) # 将 x 后的内容全部清空
文件修改的俩种方式
首先,文件其实并没有修改这一说法,只有覆盖这一说法
因为在你文件里的这段文字的前后,其实可能都满满的存放着别的东西。如果你在这段文字中加上一些东西,也就意味着后面的所有内存都要移动几格,这是不科学的。
而平时修改文件的时候,都是模拟出来的效果,具体的说有两种实现方式。
方式一
import os
with open('test.txt') as fr, \
open('test_swap.txt', 'w') as fw:
data = fr.read() # 全部读入内存,如果文件很大,会很卡
data = data.replace('tank', 'tankSB') # 在内存中完成修改
fw.write(data) # 新文件一次性写入原文件内容
# 删除原文件
os.remove('test.txt')
# 重命名新文件名为原文件名
os.rename('test_swap.txt', '37r.txt')
print('done...')
方式二
import os
with open('37r.txt') as fr,\
open('37r_swap.txt', 'w') as fw:
# 循环读取文件内容,逐行修改
for line in fr:
line = line.replace('jason', 'jasonSB')
# 新文件写入原文件修改后内容
fw.write(line)
os.remove('37r.txt')
os.rename('37r_swap.txt', '37r.txt')
print('done...')
总而言之,修改文件内容的思路为:以读的方式打开原文件,以写的方式打开一个新的文件,把原文件的内容进行修改,然后写入新文件,之后利用os模块的方法,把原文件删除,重命名新文件为原文件名,达到以假乱真的目的