文件操作
文件的处理流程
- 打开文件,得到文件句柄并赋值给一个变量
- 通过句柄对文件进行操作
- 关闭文件
使用with的话 就不需要手动关闭文件了
打开文件需要用到open方法
f = open(文件名,mode=打开方式,encoding=编码,...)
# open默认会以系统的编码打开文件
# 比如文件是用gbk的编码保存的,只能用gbk编码打开,用其他编码打开就会报错
# 比如读取一个文件中的所有内容
f= open('01.txt',mode='r',encoding='utf-8')
file = f.read()
f.close()
print(file)
打开模式
r 只读==默认的模式==可以省略==如果文件不存在会抛异常
w 只写==文件不存在会创建新的文件==如果文件存在则清空文件原有内容
x 只写==创建新的文件==如果已有文件则会抛出异常
a 只追加==不会覆盖文件原有内容
带+的话 表示读写模式
带b的话 是以二进制模式只读/写/追加 (以字节的方式读写)
文件操作方法
read([size]) 可以读取size个字符并返回 如果省略size则表示读取并返回文件所有内容
readline() 只读取一行并返回
readlines() 把文件中的每行文本作为一个字符串存储列表中,返回列表 (大文件不建议使用)
write(str) 将字符串写入到文件中
writelines(list) 将字符串列表(列表中的元素只能是字符串)写入到文件 如果要换行的在字符串末尾加上换行符
b模式
str转换成bytes 需要进行encode操作 这是编码过程
bytes变回str需要进行decode操作 这个是解码过程
这是一种转换方式
还有就是通过bytes()来 进行编码
x= "大的的马尾"
bytes(x,encoding="utf-8")
Out[6]: b'\xe5\xa4\xa7\xe7\x9a\x84\xe7\x9a\x84\xe9\xa9\xac\xe5\xb0\xbe'
bytes最终的结果一定要是ascii码的形式
s = "这是一个字符串"
se = s.encode()
print(se)
# b'\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2'
print(type(se)) # <class 'bytes'>
print(se.decode()) # 这是一个字符串
open以b模式打开的情况下不能指定编码
rb
f = open('02.txt',mode='rb') # 以二进制只读的模式打开文件
file = f.read() # 读取文件内容(二进制)
f.close()
print(file)
# b'\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2'
print(file.decode()) # 使用decode(encoding="utf-8") 将bytes类型转换成str类型
# 这是一个字符串
ab
f = open('02.txt',mode='ab') # 以二进制的模式追加
f.write("\n啊啊啊啊啊啊啊啊啊啊啊".encode()) # 需要将str进行解码 变成bytes 然后写入到文件中
f.close()
windows平台的换行是\r\n 而linux平台是\n
但是python做了一个处理 读取文件换行显示的是\n
如果把newline=”” 就能看到\r\n了 (读取真正的换行符 而不知统一的\n)
文件其他方法
f.closed 查看文件是否关闭
f.flush 把内存中的数据刷到硬盘上
# pycharm中会自动进行保存
# 但是在命令行的时候就需要手动的去flush
In [1]: import os
In [2]: os.getcwd() # 查看当前路径
Out[2]: 'C:\\Users\\PuzzleX\\Desktop'
In [4]: f = open('01.txt','w',encoding="utf-8") # 以只写的模式打开一个文件
In [5]: f.write('2313213\n')
Out[5]: 8
In [6]: f.write('aaa\n')
Out[6]: 4
# 上面的两次write()都是将内容写到内存中的 打开文件是没有内容的
In [7]: f.flush() # 将内存中的内容刷到硬盘上
# 再次打开文件,文件就有内容了
f.tell() 当前光标所在位置
关于光标移动
read(3) 代表读取了3个字符
而其他文件内的光标移动都是以字节为单位的
f.seek() 控制光标移动
由于seek是操作的字节,所以seek要以b模式操作
seek有三个模式(第二个参数)
0 从开头开始
1 相对于上一次光标的位置
2 从文件末尾开始, 第一个参数传负数
f.truncate() 文件截断
该方法不能用w和w+ 模式打开文件
f = open('02.txt', mode='r+', encoding="utf-8", newline='')
file = f.truncate(10)
f.close()
# 这样文件只剩下10个字节
案例:读取文件的最后一行
不使用seek的情况下
f = open('02.txt', mode='rb')
file = f.readlines()
f.close()
print(file[-1].decode())
如果文件过大的话 readlines() 这步操作可能会撑爆内存
所以以后循环文件都是for i in f: 这样做
那么获取最后一行内容
f = open('02.txt', mode='rb')
for i in f: # 这种方式是一行一行取
offset = -10 # 设置一个偏移量
while True:
# 首先用seek的2模式从末尾开始移动光标
# 然后使用f.readlines() 光标之后的内容
# 如果data的长度>1 说明已经读取了不止一行
# 然后取data[-1] 就拿到了文件的最后一行
f.seek(offset, 2)
data = f.readlines()
if len(data) > 1:
print("文件的最后一行是 {0}".format(data[-1].decode()))
break
offset *= 2