python文件处理
python文件处理
一、文件操作
1.1、基础流程
# 1、打开文件,由引用程序向系统发起系统调用open(),操作系统打开文件对应的磁盘空间,并赋值给一个变量f
f = open('a.txt', encoding='UTF-8')
# 2、调用文件对象的读方法,
date = f.read()
# 3、输出文件内容
print(date)
# 4、关闭文件,向操作系统发起关闭文件的请求,回收系统资源
f.close()
1.2、资源回收与with上下文管理
打开一个文件包含两部分资源:应用程序的变量 f 和操作系统打开的文件。在操作完毕一个文件的时候,必须把与该文件相关的这两部分资源回收掉,回收方法为:
# 回收操作系统打开的文件资源
f.close()
# 回收应用程序的变量
del f
del f 一定要发生在 f.close() 之后,否则就会导致操作系统打开的文件无法关闭,浪费资源
而python的垃圾回收机制决定了我们无需考虑 del f
这就要求我们操作完成文件之后,一定要记住 f.close()
但是虽然关闭文件如此重要,但是我们还是会忘记,因此,Python提供了 with 关键字来帮助我们管理上下文
# 1、在执行完子代码块后,with会自动执行 f.close()
with open('a.txt', 'r') as f:
data = f.read()
print(data)
# 2、可以用with同时打开多个文件,使用逗号分割
with open('a.txt', 'r') as f_a, open('b.txt', 'r') as f_b:
data = f_a.read()
print(data)
print()
data = f_b.read()
print(data)
1.3、指定操作文件的字符编码
open() 是由操作系统打开文件,如果打开的是文本文件,会涉及到字符编码的文艺,如果没有为open()指定编码,那么操作系统会使用自己的默认字符编码去操作文件;
如果要保持不乱码,文件以什么方式存储的,就要以什么方式打开
f = open('a.txt', encoding='UTF-8')
data = f.read()
print(data)
f.close()
二、文件的操作模式
2.1、控制文件读写的模式
- r 只读模式(默认)
- w 只写模式
- a 只追加写
只读模式
with open('a.txt', encoding='UTF-8') as f:
data = f.read()
print(data)
只写模式
# 文件不存在时会创建空文档,文件存在时会清空文件,文件指针指向文件开头
with open('a.txt', 'w')as f:
f.write('你好\n')
f.write('我是\n')
f.write('大家好\n')
f.write('111\n222\n333\n')
追加模式
# 文件不存在时会创建空文件件,文件存在时会讲文件指针指向文件末尾
with open('a.txt', 'a')as f:
f.write('卧室\n')
f.write('121\n232\n343\n')
读写模式
方式 | 说明 |
---|---|
r+ | 文件指针指向文件开头,如果文件不存在则爆出异常 |
w+ | 如果文件存在则会被覆盖,如果文件不存在则创建新文件 |
a+ | 文件指针指向文件末尾,如果文件不存在则创建新文件 |
2.2、控制文件读写内容模式
t/b模式均不能单独使用,必须与r/w/a之一结合使用
t 文本模式
# 如果我们打开文件指定的是r/w/a,那么其默认就是rt/wt/at
with open('a.txt', 'rt') as f:
data = f.read()
print(data)
with open('a.txt', 'wt') as f:
indata = 'df'
f.write(indata)
b 二进制模式
with open('a.txt', 'wb') as f:
msg = "hello"
indata = msg.encode('UTF-8')
f.write(indata)
with open('a.txt', 'rb') as f:
data = f.read()
print(type(data))
<class 'bytes'>
模式对比
1、在操作纯文本文件方面t模式帮我们省去了编码与解码的环节,b模式则需要手动编码与解码,所以此时t模式更为方便
2、针对非文本文件(如图片、视频、音频等)只能使用b模式
3、在b模式不能用encoding来指定编码
拷贝demo
src_file = input('源文件路径').strip()
dst_file = input('目标文件路径').strip()
with open(f'{src_file}', 'rb') as src_f, open(f'{dst_file}', 'wb') as dst_f:
for line in src_f:
dst_f.write(line)
三、操作文件的方法
方法解释
文件对象方法 | 说明 |
---|---|
f.read() | 有参数表从开头读多少个字节,没有读取所有内容。读小文件推荐 |
f.readline() | 读取一行内容,光标移动到第二行首部.读大文件推荐,或者 for line in 遍历 |
f.readlines() | 读取每一行内容,存放于列表中.返回值是一个列表包含'\n'.读小文推荐 |
f.write() | f.write('1111\n222\n') #针对文本模式的写,需要自己写换行符。内容必须是 字符串 |
f.write() | f.write('1111\n222\n'.encode('utf-8')) #针对b模式的写,需要自己写换行符。返回是int 字符数 |
f.writelines() | f.writelines(['333\n','444\n']) #文本模式。列表元素必须是 字符串 |
f.writelines() | f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式 |
f.seek(x,y) | seek(x, 0):从开始位置向右 x 个字符 |
f.seek(x,y) | seek(x, 1):当前位置往右移动 x 个字符 |
f.seek(x,y) | seek(-x, 2):文件的结尾向左移动 x 个字符 |
f.tell() | 返回文件的当前位置 |
f.truncate() | 清空文件,配合f.seek(0) 使用,调整指针位置 |
f.closed | 文件是否关闭 |
f.flush() | 立刻将文件内容从内存刷到硬盘 |
f.readable() | 文件是否可读 |
f.writable() | 文件是否可写 |
f.name | 文件名字 |
3.1、读操作
# 读取所有内容,执行完读取操作后,文件指针指向文件末尾
f.read()
# 读取一行内容,执行完读取操作后,文件指针指向第二行首
f.readline()
# 读取每一行内容,存放到列表中
f.readlines()
f.read() 和 f.readlines() 都是一次性读取所有内容,如果内容过大会导致内存溢出,如果需要读取大文件,可以分次读入
方式一
# 同一时刻只读取一行内容到内存里
with open('a.txt', 'rt', encoding='UTF-8') as f:
for line in f:
print(line)
方式二
# 同一时刻只读取1024个Bytes到内存中
with open('a.txt', 'rb') as f:
while 1:
data = f.read(1024)
if len(data) == 0:
break
print(data)
3.2、写操作
f.write('1111\n222\n333')
f.write('www\neee\n'.encode('UTF-8'))
f.writelines(['111\n', '222\n', '333'])
f.writelines([bytes('333\n',encoding='UTF-8'),'sss\n'.encode('UTF-8')])
3.3、seek:控制文件内指针的移动
文件内指针的移动都是以Bytes为单位的,只有在t模式下的f.read(n),此时 n 的单位是字符,也就是多少个字符的含义
with open('a.txt', 'rt')as f:
data = f.read(3)
print(data)
with open('b.txt', 'rb') as f:
data = f.read(2)
print(data)
之前文件内指针的移动都是由 读/写 操作而被动触发的,若想读取文件某一特定位置的数据,则需要用 f.seek 方法控制文件内指针的移动
0 模式可以在 b 或者 t 模式使用
1/2模式只能在 b 模式下使用
f.seek(指针移动的字节数,模式控制)
0 默认的模式,该模式代表指针的移动的字节数是以文件开头为参照的
1 该模式代表指针移动的字节数是以当前所在的位置为参照的
2 该模式代表指针移动的字节数是以文件末尾为参照的
写入文件
with open('a.txt', 'wt', encoding='UTF-8')as f:
s = 'abc芜湖'
f.write(s)
with open('a.txt', 'rt', encoding='UTF-8') as f:
data = f.read()
print('文件内容:', data)
文件内容: abc芜湖
0 模式
with open('a.txt', 'rt', encoding='UTF-8') as f:
f.seek(3,0)
print(f.tell())
print(f.read())
3
芜湖
with open('a.txt', 'rt', encoding='UTF-8') as f:
f.seek(6,0)
print(f.tell())
print(f.read())
6
湖
1 模式
with open('a.txt', 'rb') as f:
f.seek(3,1)
print(f.tell())
f.seek(4,1)
print(f.tell())
3
7
2 模式
with open('a.txt', 'rb') as f:
f.seek(0, 2)
print(f.tell())
f.seek(-3, 2)
print(f.read().decode('UTF-8'))
9
湖
demo
import time
with open('access.log', 'rb') as f:
f.seek(0,2)
while 1:
line = f.readline()
if len(line) == 0:
time.sleep(0.5)
else:
print(line.decode('UTF-8'), end='')
四、文件修改
with open('a.txt', 'wt', encoding='UTF-8') as f:
data = "TimCook USA 185 65 12312312321\nJson USA 163 60 14324324234\nTom USA 175 62 1231243423421"
f.write(data)
with open('a.txt', 'rt', encoding='UTF-8') as f:
res = f.read()
print('修改之前:\n', res)
with open('a.txt', 'r+t', encoding='UTF-8') as f:
f.seek(7)
f.write('<Apple>')
with open('a.txt', 'r', encoding='UTF-8') as f:
res = f.read()
print('修改之后:\n', res)
修改之前:
TimCook USA 185 65 12312312321
Json USA 163 60 14324324234
Tom USA 175 62 1231243423421
修改之后:
TimCook<Apple>5 65 12312312321
Json USA 163 60 14324324234
Tom USA 175 62 1231243423421
磁盘空间是无法修改的,磁盘中的数据更新都是用新数据覆盖旧数据
内存中的数据是可以修改的
修改文件的大致思路是将文件内容读取到内存,然后在内存中修改完成,再讲内存中的内容覆盖回磁盘
方式一
将文件内容一次性全部读取到内存,然后在内存中修改完成之后再覆写会源文件
优点:在文件修改过程中同一份数据只有一份
缺点:会过多占用内存
with open('a.txt', 'wt', encoding='UTF-8') as f:
data = "TimCook USA 185 65 12312312321\nJson USA 163 60 14324324234\nTom USA 175 62 1231243423421"
f.write(data)
with open('a.txt', 'rt', encoding='UTF-8') as f:
res = f.read()
print('修改之前:\n',res)
with open('a.txt', 'r+t', encoding='UTF-8') as f:
f.write(res.replace('USA', 'CHINA'))
with open('a.txt', 'r', encoding='UTF-8') as f:
res = f.read()
print('修改之后:\n',res)
修改之前:
TimCook USA 185 65 12312312321
Json USA 163 60 14324324234
Tom USA 175 62 1231243423421
修改之后:
TimCook CHINA 185 65 12312312321
Json CHINA 163 60 14324324234
Tom CHINA 175 62 1231243423421
方式二
以读的方式打开源文件,以写的方式打开一个临时文件,一行行读取源文件内容,修改完之后写入临时文件,删除源文件,将临时文件重命名为源文件名
优点:不会占用过多的内存
缺点:在文件修改过程中同一份数据保存了两份
import os
with open('a.txt', 'wt', encoding='UTF-8') as f:
data = "TimCook USA 185 65 12312312321\nJson USA 163 60 14324324234\nTom USA 175 62 1231243423421"
f.write(data)
with open('a.txt', 'rt', encoding='UTF-8') as f:
res = f.read()
print('修改之前:\n',res)
with open('a.txt', 'r') as src_f, open('.a.txt.swap', 'w') as dst_f:
for line in src_f:
dst_f.write(line.replace('USA', 'China'))
os.remove('a.txt')
os.rename('.a.txt.swap', 'a.txt')
with open('a.txt', 'r') as f:
res = f.read()
print('修改之后:\n',res)
修改之前:
TimCook USA 185 65 12312312321
Json USA 163 60 14324324234
Tom USA 175 62 1231243423421
修改之后:
TimCook China 185 65 12312312321
Json China 163 60 14324324234
Tom China 175 62 1231243423421