文件操作基本流程 電腦系統分為:電腦硬體,操作系統,應用程式三部分。 我們用python或其他語言編寫的應用程式若想要把數據永久保存下來,必須要保存於硬碟中,這就涉及到應用程式要操作硬體,眾所周知,應用程式是無法直接操作硬體的,這就用到了操作系統。操作系統把複雜的硬體操作封裝成簡單的介面給用戶/ ...
文件操作基本流程
電腦系統分為:電腦硬體,操作系統,應用程式三部分。
我們用python或其他語言編寫的應用程式若想要把數據永久保存下來,必須要保存於硬碟中,這就涉及到應用程式要操作硬體,眾所周知,應用程式是無法直接操作硬體的,這就用到了操作系統。操作系統把複雜的硬體操作封裝成簡單的介面給用戶/應用程式使用,其中文件就是操作系統提供給應用程式來操作硬碟虛擬概念,用戶或應用程式通過操作文件,可以將自己的數據永久保存下來。
有了文件的概念,我們無需再去考慮操作硬碟的細節,只需要關註操作文件的流程:
1. 打開文件,得到文件句柄並賦值給一個變數
2. 通過句柄對文件進行操作
3. 關閉文件
1 #1. 打開文件,得到文件句柄並賦值給一個變數 2 f=open('a.txt','r',encoding='utf-8') #預設打開模式就為r 3 4 #2. 通過句柄對文件進行操作 5 data=f.read() 6 7 #3. 關閉文件 8 f.close()coding
1、由應用程式向操作系統發起系統調用open(...)
2、操作系統打開該文件,並返回一個文件句柄給應用程式
3、應用程式將文件句柄賦值給變數f
關閉文件的 註意事項
1 打開一個文件包含兩部分資源:操作系統級打開的文件+應用程式的變數。在操作完畢一個文件時,必須把與該文件的這兩部分資源一個不落地回收,回收方法為: 2 1、f.close() #回收操作系統級打開的文件 3 2、del f #回收應用程式級的變數 4 5 其中del f一定要發生在f.close()之後,否則就會導致操作系統打開的文件還沒有關閉,白白占用資源, 6 而python自動的垃圾回收機制決定了我們無需考慮del f,這就要求我們,在操作完畢文件後,一定要記住f.close() 7 8 雖然我這麼說,但是很多同學還是會很不要臉地忘記f.close(),對於這些不長腦子的同學,我們推薦傻瓜式操作方式:使用with關鍵字來幫我們管理上下文 9 with open('a.txt','w') as f: 10 pass 11 12 with open('a.txt','r') as read_f,open('b.txt','w') as write_f: 13 data=read_f.read() 14 write_f.write(data)View Code
文件編碼
f=open(...)是由操作系統打開文件,那麼如果我們沒有為open指定編碼,那麼打開文件的預設編碼很明顯是操作系統說了算了,操作系統會用自己的預設編碼去打開文件,在windows下是gbk,在linux下是utf-8。
1 #這就用到了上節課講的字元編碼的知識:若要保證不亂碼,文件以什麼方式存的,就要以什麼方式打開。 2 f=open('a.txt','r',encoding='utf-8')View Code
文件的打開模式
文件句柄 = open('文件路徑', '模式')
模式可以是以下方式以及他們之間的組合:
Character | Meaning |
‘r' | open for reading (default) |
‘w' | open for writing, truncating the file first |
‘a' | open for writing, appending to the end of the file if it exists |
‘b' | binary mode |
‘t' | text mode (default) |
‘+' | open a disk file for updating (reading and writing) |
‘U' | universal newline mode (for backwards compatibility; should not be used in new code) |
1. 打開文件的模式有(預設為文本模式):
r ,只讀模式【預設模式,文件必須存在,不存在則拋出異常】
w,只寫模式【不可讀;不存在則創建;存在則清空內容】
a, 之追加寫模式【不可讀;不存在則創建;存在則只追加內容】
2. 對於非文本文件,我們只能使用b模式,"b"表示以位元組的方式操作(而所有文件也都是以位元組的形式存儲的,使用這種模式無需考慮文本文件的字元編碼、圖片文件的jgp格式、視頻文件的avi格式)
rb
wb
ab
註:以b方式打開時,讀取到的內容是位元組類型,寫入時也需要提供位元組類型,不能指定編碼
3."+" 表示可以同時讀寫某個文件
r+, 讀寫【可讀,可寫】
w+,寫讀【可讀,可寫】
a+, 寫讀【可讀,可寫】
x, 只寫模式【不可讀;不存在則創建,存在則報錯】
x+ ,寫讀【可讀,可寫】
xb
由於歷史的原因,換行符在不同的系統中有不同模式,比如在 unix中是一個\n,而在windows中是‘\r\n’,用U模式打開文件,就是支持所有的換行模式,也就說‘\r’ '\n' '\r\n'都可表示換行 t是windows平臺特有的所謂text mode(文本模式),區別在於會自動識別windows平臺的換行符。
Files opened in binary mode (appending 'b' to the mode argument) return contents as bytes objects without any decoding.
b是以二進位的形式來讀文件,但是顯示出來的卻不是0101,而是以位元組的形式顯示出來。 一個位元組是8位二進位,所以電腦是自動幫你進行了轉換。 請不要誤會b模式是按照位元組讀。
文件內的游標移動
一: read(3):
1. 文件打開方式為文本模式時,代表讀取3個字元
2. 文件打開方式為b模式時,代表讀取3個位元組
二: 其餘的文件內游標移動都是以位元組為單位如seek,tell,truncate
註意:
1. seek有三種移動方式0,1,2,其中1和2必須在b模式下進行,但無論哪種模式,都是以bytes為單位移動的
2. truncate是截斷文件,所以文件的打開方式必須可寫,但是不能用w或w+等方式打開,因為那樣直接清空文件了,所以truncate要在r+或a或a+等模式下測試效果
with上下文管理
打開一個文件包含兩部分資源:操作系統級打開的文件+應用程式的變數。在操作完畢一個文件時,必須把與該文件的這兩部分資源一個不落地回收,回收方法為:
1、f.close() 回收操作系統級打開的文件
2、del f 回收應用程式級的變數
1 with open('a.txt','w') as f: 2 pass 3 4 with open('a.txt','r') as read_f,open('b.txt','w') as write_f: 5 data=read_f.read() 6 write_f.write(data)View Code
文件的修改
文件的數據是存放於硬碟上的,因而只存在覆蓋、不存在修改這麼一說,我們平時看到的修改文件,都是模擬出來的效果,具體的說有兩種實現方式:
方式一:將硬碟存放的該文件的內容全部載入到記憶體,在記憶體中是可以修改的,修改完畢後,再由記憶體覆蓋到硬碟(word,vim,nodpad++等編輯器)
1 import os 2 3 with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f: 4 data=read_f.read() #全部讀入記憶體,如果文件很大,會很卡 5 data=data.replace('alex','SB') #在記憶體中完成修改 6 7 write_f.write(data) #一次性寫入新文件 8 9 os.remove('a.txt') 10 os.rename('.a.txt.swap','a.txt')View Code
方式二:將硬碟存放的該文件的內容一行一行地讀入記憶體,修改完畢就寫入新文件,最後用新文件覆蓋源文件
1 import os 2 3 with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f: 4 for line in read_f: 5 line=line.replace('alex','SB') 6 write_f.write(line) 7 8 os.remove('a.txt') 9 os.rename('.a.txt.swap','a.txt')View Code
python中對文件、文件夾(文件操作函數)的操作需要涉及到os模塊和shutil模塊。
得到當前工作目錄,即當前Python腳本工作的目錄路徑: os.getcwd()
返回指定目錄下的所有文件和目錄名:os.listdir()
函數用來刪除一個文件:os.remove()
刪除多個目錄:os.removedirs(r“c:\python”)
檢驗給出的路徑是否是一個文件:os.path.isfile()
檢驗給出的路徑是否是一個目錄:os.path.isdir()
判斷是否是絕對路徑:os.path.isabs()
檢驗給出的路徑是否真地存:os.path.exists()
返回一個路徑的目錄名和文件名:os.path.split() eg os.path.split('/home/swaroop/byte/code/poem.txt') 結果:('/home/swaroop/byte/code', 'poem.txt')
分離擴展名:os.path.splitext()
獲取路徑名:os.path.dirname()
獲取文件名:os.path.basename()
運行shell命令: os.system()
讀取和設置環境變數:os.getenv() 與os.putenv()
給出當前平臺使用的行終止符:os.linesep Windows使用'\r\n',Linux使用'\n'而Mac使用'\r'
指示你正在使用的平臺:os.name 對於Windows,它是'nt',而對於Linux/Unix用戶,它是'posix'
重命名:os.rename(old, new)
創建多級目錄:os.makedirs(r“c:\python\test”)
創建單個目錄:os.mkdir(“test”)
獲取文件屬性:os.stat(file)
修改文件許可權與時間戳:os.chmod(file)
終止當前進程:os.exit()
獲取文件大小:os.path.getsize(filename)
文件操作:
os.mknod("test.txt") 創建空文件
fp = open("test.txt",w) 直接打開一個文件,如果文件不存在則創建文件
關於open 模式:
w 以寫方式打開,
a 以追加模式打開 (從 EOF 開始, 必要時創建新文件)
r+ 以讀寫模式打開
w+ 以讀寫模式打開 (參見 w )
a+ 以讀寫模式打開 (參見 a )
rb 以二進位讀模式打開
wb 以二進位寫模式打開 (參見 w )
ab 以二進位追加模式打開 (參見 a )
rb+ 以二進位讀寫模式打開 (參見 r+ )
wb+ 以二進位讀寫模式打開 (參見 w+ )
ab+ 以二進位讀寫模式打開 (參見 a+ )
fp.read([size]) #size為讀取的長度,以byte為單位
fp.readline([size]) #讀一行,如果定義了size,有可能返回的只是一行的一部分
fp.readlines([size]) #把文件每一行作為一個list的一個成員,並返回這個list。其實它的內部是通過迴圈調用readline()來實現的。如果提供size參數,size是表示讀取內容的總長,也就是說可能只讀到文件的一部分。
fp.write(str) #把str寫到文件中,write()並不會在str後加上一個換行符
fp.writelines(seq) #把seq的內容全部寫到文件中(多行一次性寫入)。這個函數也只是忠實地寫入,不會在每行後面加上任何東西。
fp.close() #關閉文件。python會在一個文件不用後自動關閉文件,不過這一功能沒有保證,最好還是養成自己關閉的習慣。 如果一個文件在關閉後還對其進行操作會產生ValueError
fp.flush() #把緩衝區的內容寫入硬碟
fp.fileno() #返回一個長整型的”文件標簽“
fp.isatty() #文件是否是一個終端設備文件(unix系統中的)
fp.tell() #返迴文件操作標記的當前位置,以文件的開頭為原點
fp.next() #返回下一行,並將文件操作標記位移到下一行。把一個file用於for … in file這樣的語句時,就是調用next()函數來實現遍歷的。
fp.seek(offset[,whence]) #將文件打操作標記移到offset的位置。這個offset一般是相對於文件的開頭來計算的,一般為正數。但如果提供了whence參數就不一定了,whence可以為0表示從頭開始計算,1表示以當前位置為原點計算。2表示以文件末尾為原點進行計算。需要註意,如果文件以a或a+的模式打開,每次進行寫操作時,文件操作標記會自動返回到文件末尾。
fp.truncate([size]) #把文件裁成規定的大小,預設的是裁到當前文件操作標記的位置。如果size比文件的大小還要大,依據系統的不同可能是不改變文件,也可能是用0把文件補到相應的大小,也可能是以一些隨機的內容加上去。
目錄操作:
os.mkdir("file") 創建目錄
複製文件:
shutil.copyfile("oldfile","newfile") oldfile和newfile都只能是文件
shutil.copy("oldfile","newfile") oldfile只能是文件夾,newfile可以是文件,也可以是目標目錄
複製文件夾:
shutil.copytree("olddir","newdir") olddir和newdir都只能是目錄,且newdir必須不存在
重命名文件(目錄)
os.rename("oldname","newname") 文件或目錄都是使用這條命令
移動文件(目錄)
shutil.move("oldpos","newpos")
刪除文件
os.remove("file")
刪除目錄
os.rmdir("dir")只能刪除空目錄
shutil.rmtree("dir") 空目錄、有內容的目錄都可以刪
轉換目錄
os.chdir("path") 換路徑
1 將文件夾下所有圖片名稱加上'_fc'
1 # -*- coding:utf-8 -*- 2 import re 3 import os 4 import time 5 #str.split(string)分割字元串 6 #'連接符'.join(list) 將列表組成字元串 7 def change_name(path): 8 global i 9 if not os.path.isdir(path) and not os.path.isfile(path): 10 return False 11 if os.path.isfile(path): 12 file_path = os.path.split(path) #分割出目錄與文件 13 lists = file_path[1].split('.') #分割出文件與文件擴展名 14 file_ext = lists[-1] #取出尾碼名(列表切片操作) 15 img_ext = ['bmp','jpeg','gif','psd','png','jpg'] 16 if file_ext in img_ext: 17 os.rename(path,file_path[0]+'/'+lists[0]+'_fc.'+file_ext) 18 i+=1 #註意這裡的i是一個陷阱 19 #或者 20 #img_ext = 'bmp|jpeg|gif|psd|png|jpg' 21 #if file_ext in img_ext: 22 # print('ok---'+file_ext) 23 elif os.path.isdir(path): 24 for x in os.listdir(path): 25 change_name(os.path.join(path,x)) #os.path.join()在路徑處理上很有用 26 27 28 img_dir = 'D:\\xx\\xx\\images' 29 img_dir = img_dir.replace('\\','/') 30 start = time.time() 31 i = 0 32 change_name(img_dir) 33 c = time.time() - start 34 print('程式運行耗時:%0.2f'%(c)) 35 print('總共處理了 %s 張圖片'%(i)) 36 37 輸出結果: 38 39 程式運行耗時:0.11 40 總共處理了 109 張圖片View Code