文件是操作系统作为用户或应用程序提供的一个读写硬盘的虚拟单位。文件的操作时基于文件,文件的操作核心就是:读和写。
1、文件的作用
内存无法永久保存数据,但凡我们想要永久保存数据都需要把文件保存到硬盘中,而操作文件就可以实现对硬件的操作。
2、文件的操作
如果我们需要打开一个文件,需要向操作系统发起请求,要求操作系统打开文件,占用操作系统资源。
Python中使用open()方法可以打开某个具体的文件,open()方法内写入文件路径。
从硬盘中读取数据
# 打开文件
f = open (r'E:\chd.txt')
print(f)
>>> <_io.TextIOWrapper name='E:\\chd.txt' mode='r' encoding='cp936'>
# 写入数据
f = open (r'E:\chd.txt', mode='w')
f.write('''凡事深想一层,干活多做一步。
成功的意义在于没效果才坚持!
''')
f.close() # 关闭文件 [ del f 只是回收变量f ]
f = open (r'E:\chd.txt', mode='r')
data = f.read()
print(data)
>>> E:\python\venv\Scripts\python.exe E:/python/chd.py
凡事深想一层,干活多做一步。
成功的意义在于没效果才坚持!
# 文件读取 [ bytes模式 ]
f = open (r'E:\chd.txt', mode='w')
f.write('''凡事深想一层,干活多做一步。
成功的意义在于没效果才坚持!''')
f.close()
f = open (r'E:\chd.txt', mode='rb')
data = f.read()
print(data)
>>> E:\python\venv\Scripts\python.exe E:/python/chd.py
b'\xb7\xb2\xca\xc2\xc9\xee\xcf\xeb\xd2\xbb\xb2\xe3\xa3\xac\xb8\xc9\xbb\xee\xb6\xe0\xd7\xf6\xd2\xbb\xb2\xbd\xa1\xa3\r\n\xb3\xc9\xb9\xa6\xb5\xc4\xd2\xe2\xd2\xe5\xd4\xda\xd3\xda\xc3\xbb\xd0\xa7\xb9\xfb\xb2\xc5\xbc\xe1\xb3\xd6\xa3\xa1\r\n'
文件的三种打开模式
文件操作的基础模式(默认r模式) | |
r 模式 | read |
w 模式 | write |
a 模式 | append |
注意:t、b这两种模式均不能单独使用,需要与r/w/a之一连用!
文件读写内容的格式(默认b模式) | |
t 模式 | text |
b 模式 | bytes |
1.文件打开模式之r模式
r:read只读模式,只能读不能写,文件不存在时报错。
# rt:read by text
f = open('E:\chuid.txt', mode='r',encoding='cp936')
data = f.read()
print(data)
print(f"type(data):{type(data)}")
f.close()
>>> name:chd
>>> age:27
>>> 1234
>>> type(data):<class 'str'>
# rb:read by bytes
f = open('E:\chuid.txt',mode='rb')
data = f.read()
print(data)
print(f"type(data):{type(data)}")
f.close()
>>> b'name:chd\r\nage:27\r\n1234'
>>> type(data):<class 'bytes'>
# f.read()读取文件指针会跑到文件的末端,如果再一次读取,读取的将是空格。
f = open('E:\chd.txt',mode='rt',encoding='cp936')
data1 = f.read()
data2 = f.read()
print(f"data1:{data1}")
print(f"data2:{data2}")
f.close()
>>> data1:凡事深想一层,干活多做一步。
>>> 成功的意义在于没效果才坚持!
>>> data2:
# 由于f.read()一次性读取文件的所有内容,如果文件非常大的话可能会早点电脑卡死,因此可以使用f.readline()/f.readlines()读取文件内容
f = open('E:\chd.txt',mode='rt',encoding='cp936')
print(f"f.readable():{f.readable()}")
data1 = f.readline()
data2 = f.readlines()
print(f"data1:{data1}")
print(f"data2:{data2}")
f.close()
>>> f.readable():True
>>> data1:凡事深想一层,干活多做一步。
>>> data2:['成功的意义在于没效果才坚持!']
2.文件打开模式之w模式
W:只能写,不能读,文件存在的时候会清空文件后再写入内容,文件不存在的时候会创建文件后写入内容。
# wt
f = open('E:\chuid.txt', mode='wt', encoding='cp936')
print(f"f.readable():{f.readable()}")
f.write('文件的读取')
f.write('文件的写入')
f.flush()
f.close
>>> f.readable():False
# wb
f = open('E:\chuid.txt', mode='wb')
f.write('文件的写入'.encode('unicode_escape'))
print(f"type('文件的写入'.encode('unicode_escape')):{type('文件的写入'.encode('unicode_escape'))}")
f.close
>>> type('文件的写入'.encode('unicode_escape')):<class 'bytes'>
3.文件打开模式之a模式
a:可以追加。文件存在,则在文件的末端写入文件;文件不存在,则创建文件后写入内容。
# at
f = open('E:\chd.txt', mode='at')
print(f"f.readable(): {f.readable()}")
f.write('文件读取\n')
f.write('文件写入\n')
f.write('文件追加内容\n')
f.close()
>>> f.readable(): False
With管理文件操作上下文
with open()方法不仅提供自动释放操作系统占用的方法,并且with open可以使用逗号分隔,一次性打开多个文件,实现文件的快速拷贝。
with open('E:\chd.txt', 'rt', encoding='cp936') as f:
print(f.read())
>>> E:\python\venv\Scripts\python.exe E:/python/chd.py
>>> 凡事深想一层,干活多做一步。
>>> 成功的意义在于没效果才坚持!
文件的高级应用
1.可读、可写
r + t:可读、可写
w + t:可写、可读
a + t:可追加、可读
# wt
with open('E:\chd.txt', 'wt', encoding='cp936') as fw:
print(fw.readable())
print(fw.writable())
>>> False
>>> True
# w+t
with open('E:\chd.txt', 'w+t', encoding='cp936') as fw:
print(fw.readable())
print(fw.writable())
>>> True
>>> True
# r+t
with open('E:\chd.txt', 'r+t', encoding='cp936') as fw:
print(fw.readable())
print(fw.writable())
>>> True
>>> True
2.文件内指针移动
如果我们需要再文件内容中的某一行增加内容,使用基础的r/w/a模式实现是非常困难的,因此我们需要对文件内的指针进行移动。
with open('E:\chuid.txt', 'r+t', encoding='cp936') as fr:
fr.readline()
fr.write('chuid 2021年5月25日写') # 写在文件的最后一行
硬盘上的数据没有修改一说,在硬盘上只有覆盖,即新内容覆盖以前的内容。
1、seek(offset,whence):offset代表文件指针的偏移量,偏移量的单位是字节个数
# seek()
with open('E:\chuid.txt', 'r+t') as fr:
print(f"fr.seek(4,0):{fr.seek(4,0)}") # 0相当于文件头开始;1相当于当前文件所在位置;2相当于文件末尾
# fr.seek(0,2) # 切换到文件末尾
>>> fr.seek(4,0):4
2、tell():每次统计都是从文件开头到当前指针所在位置
with open('E:\chuid.txt', 'rb') as fr:
fr.seek(4,0)
print(f"fr.tell(): {fr.tell()}")
>>> fr.tell(): 4
3、read(n):只有在模式下的read(n),n代表的是字符个数,除此之外,其他但凡涉及文件指针的都是字节个数。
# read(n)
with open('E:\chuid.txt', 'rt') as fr:
print(f"fr.read(3): {fr.read(3)}")
>>> fr.read(3): \u6
4、truncate(n):truncate(n)是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate()要在r+或a或a+等模式下测试效果。它的参照物永远是文件头。并且truncate()不加参数,相当于清空文件。
with open('E:\chuid.txt', 'ab') as fr:
fr.truncate(2) # 截断2个字节后的所有字符,如果3个字节一个字符,只能截断2/3个字符,还会遗留1/3个字符,会造成乱码
文件修改的两种方式
# 将硬盘存放该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘。
import os
with open('E:\chd.txt') as fr, \
open('E:\chd_swap.txt', 'w') as fw:
data = fr.read() # 全部读入内存,如果文件很大,会很卡
data = data.replace('chuid', 'chd') # 在内存中完成修改
fw.write(data) # 新文件一次性写入原文件内容
# 删除原文件
os.remove('E:\chd.txt')
# 重命名新文件为原文件名
os.rename('E:\chd_swap.txt', 'E:\chd.txt')
print('done...')
>>> done...
# 将硬盘存放该文件的内容一行一行的读入内存,修改完毕就写入新文件,最后用新文件覆盖原文件
import os
with open('E:\chuid.txt') as fr, \
open('E:\chuid_swap.txt', 'w') as fw:
# 循环读取文件内容,逐行修改
for line in fr:
line = line.replace('chd', 'chenhuidong')
# 修改后的新文件覆盖原文件
fw.write(line)
os.remove('E:\chuid.txt')
os.rename('E:\chuid_swap.txt', 'E:\chuid.txt')
print('done...')
>>> done...