標籤:預設 一個 磁碟 lin 結果 遍曆檔案 flush 迴圈 否則
檔案操作介紹
python中的都是用 open() 函數,調用 open() 函數,應用程式會發起系統調用 open(...) ,進而對檔案完成操作~。以下樣本均在 python3 環境中完成~
讀取檔案簡單讀取
讀取檔案樣本:
f = open(file=‘/Users/luyi/tmp/abc‘, mode=‘r‘, encoding=‘utf-8‘)data = f.read() # 讀取檔案中所有資料print(data) # 列印檔案內容f.close() # 關閉作業系統級開啟的檔案
open() 函數參數說明:
file:指定檔案路徑mode:指定開啟檔案的模式,r 表示唯讀模式,還有很多其他模式,下面會依次介紹encoding:指定從檔案中讀取的資料使用什麼解碼標準(decode),解碼後以unicode的形式存放到記憶體中~。注意:若不指定encoding,開啟檔案的預設編碼就是作業系統的預設編碼,簡體中文版的windows是gbk,linux下是utf-8。以什麼編碼存放,就應該以什麼編碼讀取~
讀取檔案操作的注意點:
1)讀取動作完成之後,需要關閉作業系統級開啟的檔案(f.close())
2)回收應用程式級的變數(del f)
Tip:f 變數沒有引用之後,python記憶體回收機制會自動回收 f 變數,無需手動進行。但是f.close()必須手動完成,否則會持續佔用系統資源,直至程式運行結束~
也有一種方式 不需要手動關閉系統級資源
with open() as f: pass# 將上述代碼進行調整with open(file = ‘/Users/luyi/tmp/abc‘, mode = ‘r‘, encoding = ‘utf-8‘) as f: data = f.read() print(data)
Tip:with段代碼運行結束,系統級開啟的檔案會自動被關閉~
with 還可以同時開啟多個檔案,如下樣本實現了檔案的檔案的逐行複製,其中涉及到的方法下面會介紹:
with open(file = ‘/Users/luyi/tmp/abc.txt‘, mode = ‘r‘, encoding=‘utf-8‘) as read_file, open(file = ‘/Users/luyi/tmp/cde.txt‘, mode = ‘w‘, encoding=‘utf-8‘) as write_file: for line in read_file: write_file.write(line)
在讀取檔案時,若不清楚正在開啟的檔案是什麼編碼,可以使用chardet模組探測檔案的編碼方式
import chardetresult = chardet.detect(open(‘/Users/luyi/tmp/abc.txt‘, mode=‘rb‘).read())print(result)結果輸出:{‘encoding‘: ‘utf-8‘, ‘confidence‘: 0.87625, ‘language‘: ‘‘}
上述樣本中,使用 ‘rb‘ 模式開啟檔案,即以唯讀,且以位元組為單位開啟檔案。非文字檔只能使用 b 模式開啟,因為檔案本身就是以位元組的形式存放在存放裝置上的。文字檔可以使用位元組模式開啟,也可以 以本文模式開啟(預設),圖片格式的檔案(jpg,png...)、視頻音頻格式檔案(mp3、mp4、avi...)則只能以位元組模式開啟。
當文字檔使用位元組模式開啟時,open函數中不能使用 encoding 參數,若要轉成unicode,只能現將資料讀到記憶體,然後手動decode~
with open(file = ‘/Users/luyi/tmp/abc.txt‘, mode = ‘rb‘, encoding = ‘utf-8‘) as f: print(f.read())# open中使用 encoding參數,會直接拋出錯誤資訊ValueError: binary mode doesn‘t take an encoding argument#############with open(file = ‘/Users/luyi/tmp/abc.txt‘, mode = ‘rb‘) as f: data = f.read() print(data) # 原樣輸出內容 print(data.decode(‘utf-8‘)) # 解碼後輸出常值內容輸出結果:b‘\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8ckitty\n‘你好,kitty
迴圈檔案
f = open("abc.txt",‘r‘,encoding="utf-8")data = f.read()
使用這種方式讀取檔案,會一次性將檔案中所有的資料讀到記憶體中,如果檔案很大,這會給記憶體造成很大的壓力,這並不是一種合理的讀取檔案方式。這時候可以逐行擷取資料~
# 使用 readline() 僅讀取文本的一行內容,游標從檔案的開頭移動到一行的末尾(唯讀一行,遇到\r 或者 \n 為止),然後讀物第二行with open(file = ‘/Users/luyi/tmp/def.txt‘, mode = ‘r‘, encoding=‘utf-8‘) as f: data = f.readline() # 僅讀取一行 print(data)# 使用 while 迴圈遍曆檔案with open(file = ‘/Users/luyi/tmp/def.txt‘, mode = ‘r‘, encoding=‘utf-8‘) as f: line = f.readline() while line: # 當 line 不為None,繼續讀取檔案 print(line, end=‘‘) # print() 內建換行功能,line中已有‘\n‘,print不用再換行,所以加上參數end=‘‘ line = f.readline()# 使用 for 迴圈遍曆 f 變數也是逐行讀取檔案內容,與 readline() 類似。這裡其實內部調用了 f 變數的next()方法,逐行迭代檔案對象,這種方式的遍曆貌似比 readline() 要來的簡單明了。with open(file = ‘/Users/luyi/tmp/def.txt‘, mode = ‘r‘, encoding=‘utf-8‘) as f: for line in f: print(line, end=‘‘)
Tip:在調用next()方法時,不能同時調用 tell() 方法擷取檔案游標位置
和 readline() 功能類似的還有個 readlines() ,readlines()會將檔案的內容一次性擷取,並儲存為列表,檔案每一行內容為列表的一個元素~
with open(file = ‘/Users/luyi/tmp/def.txt‘, mode = ‘r‘, encoding=‘utf-8‘) as f: line = f.readlines() print(type(line)) print(line)結果輸出:<class ‘list‘>[‘1.aaaaaaaaa\n‘, ‘2.bbbbbbbbb\n‘, ‘3.ccccccccc\n‘, ‘4.ddddddddd\n‘, ‘5.eeeeeeeee\n‘, ‘6.fffffffff\n‘]
寫檔案
python寫檔案,同樣使用open(),模式使用 ‘w‘(唯寫),‘wb‘(二進位寫),‘w+‘(可讀可寫)~
直接寫
f = open(file = ‘/Users/luyi/tmp/abc.txt‘, mode = ‘w‘, encoding = ‘utf-8‘)f.write(‘你好~~,hello‘)f.close() # 同樣需要注意,關閉系統層級的資源
open() 參數說明:
file:指定檔案路徑,若該目錄下檔案不存在,會建立,若檔案存在,直接覆蓋;若目錄不存在,拋出錯誤mode=‘w‘:指定為唯寫模式encoding:指定寫入到檔案時,使用的編碼通訊協定,即將 記憶體中 unicode 格式的資料 按照指定編碼通訊協定編碼後進行儲存(這裡是 encoding 過程,和read相反)
同樣可以使用 with open() 方式代替:
with open(file = ‘/Users/luyi/tmp/abc.txt‘, mode = ‘w‘, encoding = ‘utf-8‘) as f: f.write(‘你好!!,hello‘)
二進位寫
二進位寫 的模式為 ‘wb‘,當指定 mode=‘wb‘ ,寫入資料時必須傳入位元組類型的資料(bytes類型),且需要手動添加分行符號(\n)
with open(file = ‘/Users/luyi/tmp/abc.txt‘, mode = ‘wb‘) as f: f.write(‘你好~~,hello‘.encode(‘utf-8‘))
Tip:這裡由於是‘wb‘模式,write()函數中需要傳入bytes類型的資料,直接使單引號或雙引號包含的資料是 str 類型,str 類型的資料 encode 之後,返回的是 bytes類型,或者也可以使用 b‘‘ ~
with open(file = ‘/Users/luyi/tmp/abc.txt‘, mode = ‘wb‘) as f: f.write(b‘abc‘) # bytes 類型只能包含 ASCII 碼字元
同時寫入多行使用writelines()函數
with open(file = ‘/Users/luyi/tmp/abc.txt‘, mode = ‘w‘, encoding=‘utf-8‘) as f: f.writelines([‘111111\n‘, ‘222222\n‘, ‘333333\n‘]) # 需要自己添加分行符號# wb模式with open(file = ‘/Users/luyi/tmp/abc.txt‘, mode = ‘wb‘) as f: f.writelines([bytes(‘你好\n‘.encode(‘utf-8‘)), ‘kitty\n‘.encode(‘utf-8‘)])
Tip:f.flush() 可立刻將檔案內容從記憶體刷到磁碟
注意點:當以 ‘w‘ 、‘wb‘、‘w+‘(寫讀模式,很少用) 模式開啟檔案時,在開啟檔案的同時會將檔案內容清空~
讀寫入模式
開啟檔案模式還有讀寫入模式,開啟後可進行讀寫操作,即 mode=‘r+‘;
with open(file = ‘/Users/luyi/tmp/abc.txt‘, mode = ‘r+‘, encoding=‘utf-8‘) as f: print(f.read()) f.write(‘你好~~,hello‘)
追加檔案
開啟檔案時,若使用模式 “a” 或 “ab” ,則只能對檔案進行追加,即:在原來內容的尾部追加內容~
with open(file = ‘/Users/luyi/tmp/abc.txt‘, mode = ‘a‘, encoding=‘utf-8‘) as f: f.write(‘aaaaaaa\n‘) f.write(‘vvvvvvv\n‘)檔案內容:你好kittyaaaaaaavvvvvvv
檔案操作的各種模式說明
操作檔案的模式列舉
模式 |
說明 |
‘r‘ |
讀模式 |
‘w‘ |
寫入模式 |
‘a‘ |
追加模式 |
‘b‘ |
二進位模式 |
‘t‘ |
text 模式(預設) |
‘+‘ |
同時讀寫某個檔案 |
‘x‘ |
唯寫模式,檔案不存在 自動建立,檔案原先就存在則報錯 |
除了上述幾個模式,還有以上模式的各種組合~
常用的模式還有:
rb‘,‘wb‘,‘ab‘ # 非文字檔,只能使用 ‘b‘ 模式開啟
‘r+‘,‘w+‘,‘a+‘ # 都表示可讀寫,但是注意了 ‘w+‘ 模式開啟檔案,會首先清空檔案,所以一般模式 ‘w+‘ 很少用,使用模式 ‘a+‘ 時,游標會直接跳到檔案的最後,所以之前的內容讀不到~
針對檔案的其他動作
其他檔案操作的常用函數:
def writable(self, *args, **kwargs): # real signature unknown 判斷檔案是否可寫def readable(self, *args, **kwargs): # real signature unknown 判斷檔案是否可讀def fileno(self, *args, **kwargs): # real signature unknown 返迴文件控制代碼在核心中的索引值,做IO多工時可以用到def seek(self, *args, **kwargs): # real signature unknown 移動游標移到指定位置,注意這裡移動游標的單位是位元組def seekable(self, *args, **kwargs): # real signature unknown 判斷檔案是否可進行 seek 操作def tell(self, *args, **kwargs): # real signature unknown 返回當前檔案操作游標位置 def truncate(self, *args, **kwargs): # real signature unknown 按指定長度截斷檔案,經個人測試 python3中的 truncate 方法貌似已經失效
在對檔案操作的過程中,游標會不斷移動,例如readline()方法讀取一行資訊後,游標會移動至當前行的末尾,writeline()游標也會移動至當前行末尾(寫過程貌似游標一直在末尾)~
游標移動的單位和檔案被開啟的模式相關,若檔案以文字模式開啟時,read(5) 會使游標向後移動5個字元;若檔案以非文字模式開啟(‘b‘模式),則 read() 會向後移動5個位元組。seek函數不管模式是什麼,游標移動的單位都是位元組~
例如常值內容如下:
123456789abcdefghi
code:
with open(file = ‘/Users/luyi/tmp/abc.txt‘, mode = ‘r+‘, encoding=‘utf-8‘) as f: f.seek(5) print(f.readline()) print(f.tell()) # 輸出當前游標位置結果輸出:678910
.................^_^
python檔案處理