Python的文件操作
文件
文件时操作系统提供给用户/应用程序存取硬盘的一种机制。为了永久保存数据。
操作文件的步骤:
1、打开文件,得到文件句柄并赋值给一个变量。
2、通过句柄对文件进行操作。
3、关闭文件。
在Python中
1、由应用程序向操作系统发起系统调用open(...)。操作系统打开文件返回一个文件对象(或称文件句柄)赋值给变量。
f = open('/PATH/file',mode='[rwa]')
3、调用文件对象的读/写方法,会被操作系统转换为读写硬盘的操作。
f.read()
4、向操作系统发起关闭文件请求,回收系统资源。
f.close()
open()函数
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
file:文件路径,必须传参。
若是Windows系统,传入的路径分隔符为\,可能会出现\n或\t等有特殊意义的字符,可以在字符前面加上r,表示
raw-str原始字符,取消字符的特殊含义。
mode:操作模式。
r(默认的):只读模式。文件不存在则报错,文件存在文件内指针直接跳到文件开头
w:只写模式。在文件不存在时会创建空文档,文件存在会清空文件,文件指针跑到文件开头
#强调:
# 1 在文件不关闭的情况下,连续的写入,后写的内容一定跟在前写内容的后面。
# 2 如果重新以w模式打开文件,则会清空文件内容。
a:追加写模式。在文件不存在时会创建空文档,文件存在会将文件指针直接移动到文件末尾。
+ 模式:r+ w+ a+ :可读可写
w 模式与 a 模式的异同:
1、相同点:在打开的文件不关闭的情况下,连续的写入,新写的内容总会跟在前写的内容之后
2、不同点:以 a 模式重新打开文件,不会清空原文件内容,会将文件指针直接移动到文件末尾,新写的内容永远写在最后。
控制文件读写内容的模式
大前提: tb模式均不能单独使用,必须与r/w/a之一结合使用
t(默认的):文本模式
1. 读写文件都是以字符串为单位的
2. 只能针对文本文件
3. 必须指定encoding参数
b:二进制模式:
1.读写文件都是以bytes/二进制为单位的
2. 可以针对所有文件
3. 一定不能指定encoding参数
注意:操作文件时,要注意光标位置,例如写读操作,写操作完光标会在末尾,所以无法读出写入的内容
大前提: tb模式均不能单独使用,必须与r/w/a之一结合使用
可在read()之前,利用seek(0)将光标移动到首部。
encoding:指定字符编码。
如果以t模式操作文件,就要指定字符编码。不指定则为系统默认,Windows为gbk,Linux和Mac为utf-8。
为了保证打开文件不会乱码,写文件和读文件一定要以相同的字符编码。
如果是b模式,一定不要指定encoding。
文件对象内置方法
r模式
read(n):指定读取多少文件,只有在t模式下的read(n)中n表示单位是字符,其他的指针移动单位都是字节bytes。不指定则将文件全部读到内存。读多少个字符指针就会移动多少个字符。
readline():执行一次读取一行内容。
readlines():将文件全部读到内存放入一个列表中。
readable():判断是否可读。
W模式
write():将内容全部写入文件。返回写入的字符数。
writelines():传入一个可迭代对象,每次遍历一个值,写入一个值。值必须是字符串或者bytes类型。
writeable():判断是否可写。
flush():将文件立即写入硬盘。
其他方法
name:查看文件名。
encoding:查看文件编码。
truncate(n):表示保留几个字节,其余部分都删除。utf-8中一个中文占三个字节,如果只保留其中一个或两个字节,最后显示的字符会是乱码。
tell():获取指针所在字节位置。
seek(移动的字节个数,模式):
移动的字节个数:正数表示向右移动,0表示不动,负数表示向左移动。
三种模式:
0:参考文件开头。
1:参考指针当前位置。
2:参考文件末尾。
只有0模式可以在t模式下使用,1和2只能在b模式使用。
# 例如:
f.seek(3,0) # 表示将指针从文件开头向右移动3个字节。
f.seek(4,1) # 表示将指针从当前位置向右移动4个字节。
f.seek(5,2) # 表示将指针从文件末尾向右移动5个字节,指针本就在文件末尾,此时再往右移实际上并没有移动。
资源回收
打开一个文件包含两部分资源:
1、应用程序的变量f。
2、操作系统打开的文件。
在操作完毕一个文件时,必须把文件的这两部分资源全部回收。
# 回收打开的文件
f.close()
# 回收变量资源
del f
其中del f一定要发生在f.close()之后,否则就会导致操作系统打开的文件无法关闭,白白占用资源。
python自动的垃圾回收机制决定了我们无需考虑del f,这就要求我们,在操作完毕文件后,一定要记住f.close(),虽然如此强调,但是用户还是会不由自主地忘记f.close(),考虑到这一点,python提供了with关键字来帮我们管理上下文。
with上下文管理
# 1、在执行完子代码块后,with 会自动执行f.close()
with open('a.txt','w') as f:
pass
# 2、可用用with同时打开多个文件,用逗号分隔开即可,如果一行过长可以用转义符\换行。
with open('a.txt','r') as read_f,\
open('b.txt','w') as write_f:
data = read_f.read()
write_f.write(data)
-
注意:with打开文件在一段时间后会自动关闭句柄,但这个时间不固定。
如果你在with语句中以r模式打开f1文件,那么你在下面又以a模式打开f1文件,此时有可能你第二次打开f1文件时,第一次的文件句柄还没有关闭,可能会出现错误。
解决方式只能在你第二次打开此文件前,手动关闭上一个文件句柄。
手动编写一些工具
文件拷贝工具
1、以rb模式向源文件内容读到内存,如果全部读到内存,会占用大量内存空间,文件过大时此操作很危险。
2、以wb模式将源文件内容写入新文件,使用b模式就可以拷贝任意文件。
with open(r'/PATH/source_file',mode='rb') as src_f,\
open(r'/PATH/target_file',mode='wb') as tar_f:
while 1:
line = src_f.read(1024) # 指定每次读取1024字节,这样就不会占用大量内存空间,但会增加硬盘I/O操作.
if len(line) != 0:
tar_f.write(line)
else:break
文件修改工具
在硬盘中,文件并没有修改的概念。修改文件的本质是将文件读入内存中,修改完毕后再写回硬盘。
方式一
1、以r模式打开源文件,将文件内容全部读到内存。
2、在内存中修改文件。
3、以w模式打开源文件,将修改后的内容写入源文件。
这是编辑器的处理方式,因为要让用户能直接看到全部文件内容。
with open(r'/PATH/file',mode='rt',encoding='utf-8') as f:
data = f.read()
ret = data.replace(old,new) # 指定修改的内容。
with open(r'/PATH/file',mode='wt',encoding='utf-8') as f:
f.write(ret)
缺点:只能拷贝小文件,如果文件过大会占用大量内存空间。
优点:不会占用大量硬盘空间。
方式二
1、以r模式打开源文件,每次读取文件一行到内存。
2、以w模式创建一个临时文件,每修改完一行内容就写入到临时文件中。
3、修改完毕后,删除源文件,将临时文件改名为源文件。
import os
with open(r'/PATH/old_file',mode='rb') as old_f,\
open(r'/PATH/.old_file.swp',mode='wb') as new_f:
for line in old_f: # 每次读一行内容。
new_f.write(line)
os.remove('/PATH/.old_file.swp') # 删除源文件
os.rename('/PATH/new_file','/PATH/.old_file.swp') # 将临时文件改名为源文件
缺点:硬盘上会同时存在两个相同大小的文件,对硬盘空闲空间有要求。
优点:不会占用大量内存空间。
动态监测文件尾部添加的内容
模拟Linux中tail -f命令。
import time
# 以r模式打开文件,将指针置于文件末尾。
with open('/PATH/file',mode='rt',encoding='utf-8') as f:
f.seek(0,2)
while 1:
last_line = f.readline() # 不断读下一行.
if len(last_line) == 0:
time.sleep(0.1) # 如果下一行为空,则让程序暂停0.1秒,避免过多消耗CPU。
else:
print(last_line,end='') # 不为空则打印该行。