day8
万恶之源- 文件操作
本节主要内容:
1.初识文件操作
2.只读(r,rb)
3.只写(w,wb)
4.追加(a,ab)
5. r+ 读写
6. w+ 写读
7.a+写读(追加写读)
8.其他操作方法
9.文件的修改以及另一种打开文件句柄的方式
主要内容:
1.使用python来读写文件是非常简单的操作,我们使用open()函数来打开一个文件,获取到文件句柄,然后通过文件句柄就可以进行各种各样的操作了,根据打开方式的不同能够执行的操作也会有相应的差异.
打开文件的方式:r,w,a,r+,w+,a+,rb,wb,ab,r+b,w+b,a+b默认使用的是r(只读)模式
2.只读操作(r,rb)
f = open('啦啦啦',mode='r',encoding='utf-8') content = f.read() print(content) f.close()
需要注意encoding表示bytes类型,在rb模式下,不能选择encoding字符集
f = open('啦啦啦',mode='rb') content = f.read() print(content) f.close()
rb的作用:在读取非文本文件的时候,比如在读取MP3,图像,的信息的时候需要用到rb.
绝对路径: 从磁盘根目录开始一直到文件名
相对路径: 同一个文件下的文件,相对于当前这个程序所在的文件夹而言,如果在同一个文件夹中,则相对路径就是这个文件名, 如果在上一层文件夹../
推荐用相对路径,
读取文件的方法:
1. read() 将文件中的文件全部读取出来, 弊端: 占内存. 如果文件过大,容易导致内存崩溃.
f = open('../def/哇卡.txt',mode='r',enconding='utf-8') content = f.read() print(content)
2, read(n) 读取n个字符,需要注意的是,如果再次读取,那么会在当前位置继续去读而不是从头读,如果使用的rb模式,则读取出来的是n个字节.
3. readline() 一次读取一行数据,注意: readline() 结尾,注意每次读取出来的数据都会有一个\n .
所以,需要我们使用 split() 方法来去掉 \ n 或者 空格.
4.readlines() 将每一行形成一个元素,放到一个列表中,将所有的内容都读取 出来,也容易出现内存崩溃的问题,不推荐使用.
5, 循环读取, 这种方式是组好的,每次读取一行内容.不会产生内存溢出的问题.
f = open('../def/哇卡.txt',mode='r',encoding='utf-8') for line in f: print(line.strip())
注意: 读取完的文件句柄一定要关闭 f.close()
3. 写模式(w,wb)
写的时候注意, 如果没有文件,则会创建文件,如果文件存在,则将原件中原来的内容删除,再写入新内容.
f = open('哈哈',mode= 'w',encoding='utf-8') f.write('啦啦啦啦') f.flush() # 刷新, 养成好习惯. f.close()
尝试读一读
f = open('哈哈',mode='w',encoding='utf-8') f.write('笨蛋') f.read() # not readable 模式是w,不可以执行读操作. f.flush() f.close()
wb模式下, 可以不指定打开文件的编码.但是在写文件的时候必须将字符串转化成utf-8的bytes数据.
f = open('哈哈',mode='wb') f.write('本地那'.encode('utf-8')) f.flush() f.close()
4.追加(a,ab)
在追加模式下,我们写入的内容会追加在文件的结尾.
5.读写模式(r+,r+b)
对于读写模式,必须是先读,因为默认光标是在开头的,准备读取的,当读取完之后,在进行写入.
正确操作是:
f = open('哈哈',mode='r+',encoding='utf-8') content = f.read() f.write('啦啦啦啦') print(content) f.flush() f.close() #结果: 正常的读取之后,写在结尾.
记住 : r+模式下,必须是先读取,然后写入.
6.写读(w ,w+b)
先将所有的内容清空,然后写入,最后读取,但是读取的内容是空的,不常用
f = open('哈哈',mode='w+',encoding='utf-8') f.write('哈哈') content = f.read() print(content) f.flush() f.close()
7. 追加读(a+)
a+模式下,不论先读还是后读,都是读取不到数据的,
还有一些其他的带b的操作, 就是把字符换成字节,仅此而已,
8. 其他相关操作
1. seek(n) 光标移动到n位置,注意,移动的单位是byte,所以如果是utf-8的中文部分要是3的倍数.
通常我们使用seek都是移动到开头或者结尾.
移动到开头: seek(0)
移动到结尾: seek(0,2) seek的第二个参数表示的是从哪个位置进行便宜,默认是0,表示开头,
1表示当前位置, 2表示结尾.
f = open('哈哈',mode='r+',encoding='utf-8') f.seek(0) #光标移动到开头. content = f.read() # 读取内容,此时光标移动到结尾. print(content) f.seek(0) # 光标继续移动到开头. f.seek(0,2) # 将光标移动到结尾. content2 = f.read() # 读取内容,什么都没有. print(content2) f.seek(0) # 移动到开头 f.write('张国荣') # 写入信息,此时光标在 9 中文3*3个 = 9 f.flush() f.close()
2. tell() 使用tell()可以帮我们获取到当前光标在什么位置.
f = open('哈哈',mode='r+',encoding='utf-8') f.seek(0) # 光标移动到开头. content = f.read() #读取内容,此时光标移动到结尾 print(content) f.seek(0) # 再次将光标移动到开头 f.seek(0,2) # 将光标移动到结尾 content2 = f.read() # 读取内容,什么都没有 print(content2) f.seek(0) # 移动到开头 f.write('张国荣') # 写入信息,此时光标在9 中文3 * 3个 = 9 print(f.tell()) # 光标位置 9 f.flush() f.close()
f = open('哈哈',mode='r+',encoding='utf-8') f.seek(0) # 光标移动到开头. content = f.read() #读取内容,此时光标移动到结尾 print(content) f.seek(0) # 再次将光标移动到开头 f.seek(0,2) # 将光标移动到结尾 content2 = f.read() # 读取内容,什么都没有 print(content2) f.seek(0) # 移动到开头 f.write('张国荣') # 写入信息,此时光标在9 中文3 * 3个 = 9 print(f.tell()) # 光标位置 9 f.flush() f.close()
3, truncate() 截断文件
f = open('哈哈',mode='w',encoding='utf-8') f.write('本地') # 写入2个字符 f.seek(3) # 光标移动到3,也就是两个字之间 f.truncate() # 删除光标后面的所有内容 f.close()
深坑注意: 在 r+模式下, 如果读取到了内容,不论读取内容多少,光标显示的是多少,再写入或者操作文件的时候都是在结尾进行的操作.
9. 修改以及另一种打开文件的方式
文件修改:只能将文件中的内容读取到内存中,将信息修改完毕,然后将源文件删除,将新文件的名字改成老文件的名字.
# 文件修改 import os with open('a',mode='r',encoding='utf-8') as f , \ open('a1',mode='w',encoding='utf-8') as f1: s = f.read() s1 = s.replace('笨蛋','脉动') f1.write(s1) os.remove('a') # 删除源文件 os.rename('a1','a') # 重命名新文件
# 弊端是: 一次将所有的内容进行读取,内存溢出,
# 解决方案是: 一行一行的读取和操作.
# 文件修改 # 一行一行的进行读取和操作 import os with open('a',mode='r',encoding='utf-8') as f , \ open('a1',mode='w',encoding='utf-8') as f1: for line in f.readlines(): s = line.replace('笨蛋','脉动') f1.write(s) os.remove('a') # 删除源文件 os.rename('a1','a') # 重命名新文件