第四章 Python 文件處理
第1章 文件處理
1.1 文件操作流程
1、 打開文件,得到文件句柄並賦值給一個變量
2、 通過句柄對文件進行操作
3、 關閉文件
1.2 具體操作
1、打開文件,得到文件句柄並賦值給一個變量
f=open(‘db.txt‘,‘r‘,encoding=‘utf-8‘)
2、通過句柄對文件進行操作
data=f.read()
3、 關閉文件
f.close() #回收操作系統資源
1.3 流程分析
f=open(‘db.txt‘,‘r‘,encoding=‘utf-8‘)
1、由應用程序向操作系統發起系統調用:open(...)
2、操作系統打開該文件,並返回一個文件句柄給應用程序
3、應用程序將文件句柄賦值給變量f
1.4 資源回收
1、 打開一個文件包含兩部分資源:
操作系統級打開的文件 和 應用程序的變量。
在操作完畢一個文件時,必須把與該文件的這兩部分資源一個不落地回收,方法是:
1) f.close() #回收操作系統級打開的文件;
2) del f #回收應用程序級的變量;python解釋器自動的垃圾回收機制已經替我們做了
註意:
1) del f 一定要發生在 f.close()之後,否則就會導致操作系統打開的文件沒有關閉,浪費資源,記住在操作完畢文件後,一定要進行f.close
2) 打開文件的編碼是以操作系統的編碼為準的,除非open()指定encoding=‘編碼‘ )
1.5 with 關鍵字
with的作用:上下文管理,它會幫我們來關閉文件(f.close())
with open(‘a.txt‘,‘r‘,encoding=‘utf-8‘) as f:
data=f.read()
### 支持同時管理多個文件
with open(‘a.txt‘,‘r‘,encoding=‘utf-8‘) as read_f,open(‘b.txt‘,‘r‘,encoding=‘utf-8‘) as write_f:
data=read_f.read()
write_f.write(data)
1.6 字符編碼問題
f=open(...)是由操作系統打開文件,那麽如果我們沒有為open指定編碼,那麽打開文件的默認編碼很明顯是操作系統說了算了,操作系統會用自己的默認編碼去打開文件:
在windows下是gbk,在linux下是utf-8。
這就用到了上節課講的字符編碼的知識:若要保證不亂碼,文件以什麽方式存的,就要以什麽方式打開。
f=open(‘a.txt‘,‘r‘,encoding=‘utf-8‘)
第2章 打開文件的模式
文件句柄 = open(‘文件路徑‘, ‘模式‘,‘字符編碼‘)
2.1 文本模式(‘t‘,text mode(default)
r ,只讀模式【默認模式,文件必須存在,不存在則拋出異常】
with open(‘a.txt‘,‘r‘,encoding=‘utf-8‘)
as f:
print(f.read())
w,只寫模式【不可讀;不存在則創建;存在則清空內容】
### 換行使用‘\n‘
with open(‘a.txt‘,‘w‘,encoding=‘utf-8‘) as f:
f.write(‘今天是2017.09.22\n‘)
f.write(‘今天是星期五\n‘)
今天是2017.09.22
今天是星期五
a, 只追加寫模式【不可讀;不存在則創建;存在則只追加內容】
with open(‘a.txt‘,‘a‘,encoding=‘utf-8‘)
as f:
f.write(‘111\n‘)
f.write(‘222\n‘)
f.write(‘333\n‘)
今天是2017.09.22
今天是星期五
111
222
333
2.2 二進制模式(‘b‘ binary mode)
對於非文本文件,我們只能使用b模式,"b"表示以字節的方式操作(而所有文件也都是以字節的形式存儲的,使用這種模式無需考慮文本文件的字符編碼、圖片文件的jgp格式、視頻文件的avi格式)
註:以b方式打開時,讀取到的內容是字節類型,寫入時也需要提供字節類型,不能指定編碼
with open(‘yuanhao.jpg‘,mode=‘rb‘) as f:
print(f.read())
### 如果對文本使用b二進制模式操作,記得要解碼成utf-8
with open(‘a.txt‘,mode=‘rb‘) as f:
data=f.read()
print(data.decode(‘utf-8‘))
### 寫入文本格式的話,需要encode utf-8
with open(‘d.txt‘,mode=‘wb‘) as f:
f.write(‘哈哈哈hello‘.encode(‘utf-8‘))
2.3 了解模式
"+" 表示可以同時讀寫某個文件
r+, 讀寫【可讀,可寫】
w+,寫讀【可讀,可寫】
a+, 寫讀【可讀,可寫】
x, 只寫模式【不可讀;不存在則創建,存在則報錯】
x+ ,寫讀【可讀,可寫】
第3章 操作文件的方法
3.1 掌握
3.1.1 read (讀取)
f.read() #讀取所有內容,光標移動到文件末尾
f.readline()
#讀取一行內容,光標移動到第二行首部
f.readlines() #讀取每一行內容,存放於列表中
### 讀取所有內容,文件大的時候不要用 read
with open(‘a.txt‘,‘r‘,encoding=‘utf-8‘)
as f_read:
print(f_read.read())
今天是2017.09.22
今天是星期五
111
222
333
### 按行讀取內容
with open(‘a.txt‘,‘r‘,encoding=‘utf-8‘)
as f_read:
print(f_read.readline())
print(f_read.readline())
今天是2017.09.22
今天是星期五
### 需要加上end=‘‘用來替換掉換行的 \n
with open(‘a.txt‘,‘r‘,encoding=‘utf-8‘)
as f_read:
print(f_read.readline(),end=‘‘) #一次讀一行
print(f_read.readline(),end=‘‘)
今天是2017.09.22
今天是星期五
### 讀所有,結果放入列表中
with open(‘a.txt‘,‘r‘,encoding=‘utf-8‘)
as f_read:
print(f_read.readlines()) #讀所有,大文件的話會很卡
[‘今天是2017.09.22\n‘, ‘今天是星期五\n‘, ‘111\n‘, ‘222\n‘, ‘333\n‘]
with open(‘a.txt‘,‘r‘,encoding=‘utf-8‘)
as f_read:
print(f_read.readlines()[0])
今天是2017.09.22
3.1.2 write (寫入)
f.write(‘1111\n222\n‘) #針對文本模式的寫,需要自己寫換行符
f.write(‘1111\n222\n‘.encode(‘utf-8‘)) #針對b模式的寫,需要自己寫換行符
f.writelines([‘333\n‘,‘444\n‘]) #文件模式
f.writelines([bytes(‘333\n‘,encoding=‘utf-8‘),‘444\n‘.encode(‘utf-8‘)]) #b模式
將列表中的內容寫入文件:
l=[‘444\n‘,‘555\n‘,‘666\n‘]
with open(‘a.txt‘,‘a‘,encoding=‘utf-8‘)
as f_write:
for line
in l:
f_write.write(line)
今天是2017.09.22
今天是星期五
111
222
333
444
555
666
### 使用writeline方法
with open(‘a.txt‘,‘a‘,encoding=‘utf-8‘)
as f_write:
f_write.writelines([‘444\n‘,‘555\n‘,‘666\n‘])
3.1.3
#遍歷文件z
with open(‘a.txt‘,encoding=‘utf-8‘) as f:
#不推薦使用
# lines=f.readlines()
# for line in lines:
#
print(line,end=‘‘)
### 推薦使用
for line in f:
print(line,end=‘‘)
3.2 了解
f.readable() #文件是否可讀
f.writable() #文件是否可讀
f.closed #文件是否關閉
f.encoding #如果文件打開模式為b,則沒有該屬性
f.flush() #立刻將文件內容從內存刷到硬盤
第4章 文件操作的其他方法
4.1 read(n)
### 以文本的模式讀文件,n代表的是字符的個數
with open(‘a.txt‘,‘r‘,encoding=‘utf-8‘)
as f:
data=f.read(3)
print(data)
今天是
### 以b的模式讀文件,n代表的是字節的個數
with open(‘a.txt‘,‘rb‘)
as f:
data=f.read(3)
print(f.tell())
print(data.decode(‘utf-8‘))
3
今
4.2 tell 返回光標位置
### tell:告訴當前光標的位置
with open(‘a.txt‘,‘r‘,encoding=‘utf-8‘)
as f:
data=f.read(3)
print(f.tell())
print(data)
9
今天是
4.3 seek 移動光標
fileObject.seek(offset[, whence])
offset -- 開始的偏移量,也就是代表需要移動偏移的字節數
whence:可選,默認值為 0。給offset參數一個定義,表示要從哪個位置開始偏移;0代表從文件開頭開始算起,1代表從當前位置開始算起,2代表從文件末尾算起。
with open(‘a.txt‘,‘r‘,encoding=‘utf-8‘)
as f:
data1=f.read()
print(‘first: ‘,data1)
print(f.tell())
#獲取當前光標位置
f.seek(0) #移動到文件開頭
data2 = f.read() #由於光標移動到文件開頭,所以文件又完全輸出一次
print(‘second: ‘,data2)
first: abc
efd
12
second: abc
efd
第5章 文件的修改
文件的數據是存放於硬盤上的,因而只存在覆蓋、不存在修改這麽一說,我們平時看到的修改文件,都是模擬出來的效果,具體的說有兩種實現方式:
方式一:將硬盤存放的該文件的內容全部加載到內存,在內存中是可以修改的,修改完畢後,再由內存覆蓋到硬盤(word,vim,nodpad++等編輯器)
e.txt >>>
alex say i have on tesla
my name is alex
alex is good
alex xxxx hahaha alex
### 方式一(占用內存過大,僅適用於小文件):把硬盤中文件的數據全部讀入內存,然後在內存裏進行修改,最後保存
import os
with open(‘e.txt‘,‘r‘,encoding=‘utf-8‘)
as f_read,\
open(‘.e.txt.swap‘,‘w‘,encoding=‘utf-8‘)
as f_write:
data=f_read.read()
data=data.replace(‘alex‘,‘sb‘)
f_write.write(data)
os.remove(‘e.txt‘)
os.rename(‘.e.txt.swap‘,‘e.txt‘)
### 方式二:一行一行地讀,一行一行地改
import os
with open(‘e.txt‘,‘r‘,encoding=‘utf-8‘)
as f_read ,open(‘e.txt.swap‘,‘w‘,encoding=‘utf-8‘)
as f_write:
for n
in f_read:
data=n.replace(‘sb‘,‘alex‘) ### 讀一行
f_write.write(data) ### 改一行
os.remove(‘e.txt‘)
os.rename(‘e.txt.swap‘,‘e.txt‘)
第6章 把文件檔數據庫
db.txt>>>
1,peigen1,38,male,1234563378
2,peigen2,28,female,1234335678
3,peigen3,18,male,123145678
4,peigen4,8,male,1234115678
5,peigen5,48,female,1232245678
6,peigen6,58,male,1234335678
with open(‘db.txt‘,‘r‘,encoding=‘utf-8‘)
as f:
for line
in f:
user_l=line.split(‘,‘)
print(user_l[1],int(user_l[2]))
peigen1 38
peigen2 28
peigen3 18
peigen4 8
peigen5 48
peigen6 58
第四章 Python 文件處理