<style> .red { color: red; } .blue{ color: blue; } .green{ color: green; } </style> # 檔案存取 ## 8-1 認識檔案路徑 - 檔案或資料夾存放在儲存裝置的方式取決於**檔案系統(File System)** - **檔案系統(File System)** 會找出檔案存放在儲存裝置的哪個位置,進而讀取上面的資料 - 不同電腦的作業系統(Operation System),可能採用不同的檔案系統 1. MS-DOS的檔案系統為FAT(File Allocation Table) 2. Windows 7/8/10的檔案系統為FAT32、NTFS(New Technology File-System)或exFAT(Extended File Allocation Table) ## 8-2 寫入檔案 ### 8-2-1 建立檔案物件 - 在Python程式中,無論是要讀取還是寫入檔案資料,<span class='red'>都必須透過中介的檔案物件</span> - 我可以使用下方的open( )函示來建立物件。當建立成功時會回傳檔案物件;相反的,當建立失敗時會發生錯誤 ```python= open(file, mode) # file為欲儲存的檔案路徑和名稱 # mode是檔案物件的存取模式,常用的有6種 ``` - 常用的有6種mode: 1. "**r**": 讀取檔案,若無此檔案會出現錯誤 2. "**w**": 寫入檔案,若無此檔案則會直接建立檔案。另外<span class='red'>寫入資料前會將檔案內的資料全部清除</span> 3. "**a**": 入檔案,若無此檔案則會直接建立檔案。另外<span class='red'>寫入的資料會附加在原檔案內容的後面</span> 4. "**r+**": 以讀寫模式開啟檔案,**會從檔案開頭寫入資料並覆蓋掉原始的內容**,若無此檔案會出現錯誤 5. "**w+**": 以讀寫模式開啟檔案,**會從檔案開頭寫入資料並先清除原檔案的內容**,若無此檔案則會直接建立檔案 6. "**a+**": 以讀寫模式開啟檔案,**會從檔案開頭寫入資料並附加在原檔案內容的後面,若無此檔案則會直接建立檔案 ```python= # 注意要使用跳脫序列 "\\" 來表示 "\" # 使用絕對路徑(absolute path) fileObject = open("D:\\vitas\\test.py", "r") # 在絕對路徑前面加上r,表示此字串為原始字串(raw string) # 這樣就不必使用跳脫序列 "\\" 來表示 "\" fileObject = open(r"D:\vitas\test.py", "r") ``` ### 8-2-2 將資料寫入檔案 ```python= # 將資料寫入檔案 fileObject = open("D:\\vitas\output.txt") # 檔案物件提供的write()方法能將資料寫進檔案 fileObject.write("大家好!") # 要記得關閉檔案 fileObject.close() ``` ## 8-3 讀取檔案 - 從檔案讀取資料的步驟如下: 1. <span class='red'>開啟檔案</span>: 使用open( )函式來建立檔案物件 2. <span class='red'>讀取檔案</span>: 使用檔案物件提供的方法來讀取資料(包含**read( )** , **readline( )** 及**readlines( )** ) 3. <span class='red'>關閉檔案</span>: 使用檔案物件提供的close( )方法關閉檔案 ### 8-3-1 使用read()方法從檔案讀取資料 ```python= read([n]) # 指標一開始是指向檔案開頭 # 上述語法會從檔案指標處讀取參數n所指定之個數的文字,然後傳回該字串 # 若參數n省略不寫,就以字串的形式回傳檔案中所有的資料 ``` ```python= # 若參數n省略不寫,就以字串的形式回傳檔案中所有的資料 fileObject = open("D:\\test.txt", "r") content = fileObject.read() print(content) fileObject.close() ``` ```python= # 上述語法會從檔案指標處讀取參數n所指定之個數的文字,然後傳回該字串 fileObject = open("D:\\test.txt", "r") str = fileObject.read([6]) print(content) fileObject.close() ``` ### 移動檔案指標 - **檔案指標**會指向目前讀取或寫入到哪個位置 - 若要自行移動,可以使用指令<span class='red'>seek( )方法,來將檔案指標移到第offset+1個位元組(byte)</span> ```python= fileObject.seek(offset) ``` ```python= fileObject = open("D:\\vitas\\test.txt", "r") # 移動指標 fileObject.seek(1) # 移動指標到開頭 fileObject.seek(0) fileObject.close() ``` ### 8-3-2 使用readline()方法從檔案讀取資料 - readline( )方法可以從檔案讀取**一行**資料(**遇到換行\n**),然後回傳該字串 - <span class='red'>若傳回空字串,則表示抵達檔案結尾</span> ```python= fileObject = open("D:\\vitas\\test.txt", "r") content = fileObject.readline() while content!='': print(content) content = fileObject.readline() # print出後繼續讀取一行資料 fileObject.close() ``` ```python= # 下方程式結果與上方相同 fileObject = open("D:\\vitas\\test.txt", "r") # 使用for迴圈印出每一行 for line in fileObject: print(line) fileObject.close() ``` ### 8-3-3 使用readlines()方法從檔案讀取資料 - readlines( )方法可以從檔案讀取**所有行**的資料,然後以串列(list)的形式傳回所有行 ```python= fileObject = open("D:\\vitas\\test.txt", "r") content = fileObject.readlines() print(content) for line in content: print(line) fileObject.close() ``` ## 8-4 with敘述 - 在檔案存取結束後,我們會使用close( )函式來關閉檔案物件,否則檔案容易被竄改 - 但若怕忘記解close( ),則<span class='red'>可以使用with敘述,來將存取檔案的動作包裝在一個區塊</span> - 也就是依但程式執行動作離開區塊,就會自動關閉檔案物件 ```pytohn= with open(file, mode) as fileObjectName: STATEMENT ``` ```python= with open("D:\\vitas\\test.txt", "r") as fileObject: content = fileObject.readlines() print(content) for line in content: print(line) ``` ## 8-5 管理檔案與目錄 ### 8-5-1 檢查檔案或目錄是否存在 ```python= os.path.exists("D:\\") # 若存在則會回傳True,反之則回傳False ``` ### 8-5-2 檢查路徑是否為檔案或目錄 ```python= os.path.isdir("D:\\") # 若路徑為目錄則會回傳True,反之則回傳False os.path.isfile("D:\\vitas\\test.txt") # 若路徑為檔案則會回傳True,反之則回傳False ``` - 前面我們有提到,如果在閱讀模式下去開啟不存在的檔案會發生錯誤。因此可以使用<span class='red'>isfile( )來確認要讀取的檔案是否存在</span> ```python= import os.path if os.path.isfile("D:\\vitas\\test.txt"): with open("D:\\vitas\\test.txt", "r") as fileObject: content = fileObject.readlines() for line in content: print(line) else: print("此檔案不存在!") ``` ### 8-5-3 取得檔案的完整路徑 ```python= os.path.abspath("test.txt") # abspath("FILE")函式可以取得參數file檔案之絕對路徑 ``` >Output >> 'D:\\vitas\\test.txt' ### 8-5-4 取得檔案的大小 ```python= os.path.getsize("test.txt") # getsize("FILE")函式可以取得參數file的檔案大小,單位為byte ``` >Output >> 148 ### 8-5-5 刪除檔案 ```python= import os file = "D:\\vitas\\test.txt" if os.path.exists(file): os.remove(file) else: print("此檔案不存在!") ``` ### 8-5-6 建立目錄 ```python= import os dir = "D:\\vitas\\dir1" if not os.path.exists(dir): os.mkdir(dir) else: print("此目錄已經存在!") ``` ### 8-5-7 刪除目錄 ```python= import os dir = "D:\\vitas\\dir1" if os.path.exists(dir): os.rmdir(dir) else: print("此目錄不存在!") ``` ### 8-5-8 複製檔案 ```python= import shutil shutil.copy("src", "dst") # copy( )的回傳值是目的路徑 shutil.copy("test.txt", "D:\\vitas\\dir1\\test2.txt") # 也可以將一個檔案內的資料複製到另一個檔案內 ``` ### 8-5-9 複製目錄 ```python= import shutil shutil.copytree("src", "dst") # copytree( )的回傳值是目的路徑 shitil.copytree("D:\\vitas\\dir1", "D:\\vitas\\dir2\\dir3") ``` ### 8-5-10 搬移檔案或目錄 ```python= import shutil shutil.move("src", "dst") # copytree( )的回傳值是目的路徑 shutil.move("test.txt", "D:\\vitas\\dir1\\test2.txt") # 將test.txt搬移到D:\vitas\dir1\test2.txt shitil.move("D:\\vitas\\dir1", "D:\\vitas\\dir2\\dir3") # 將D:\vitas\dir1搬移到D:\vitas\dir2\dir3 ``` ### 8-5-11 取得符合條件的檔案名稱 ```python= glob.glob("D:\\vitas\\*.txt") # 在D:\vitas\目錄底下找到所有副檔名是.txt的檔案 ``` >Output >> ['D:\\vitas\\a1.txt', 'D:\\vitas\\a2.txt', 'D:\\vitas\\a3.txt', D:\\vitas\\b1.txt', 'D:\\vitas\\b2.txt', 'D:\\vitas\\f1.txt'] ```python= glob.glob("D:\\vitas\\a*.txt") # 在D:\vitas\目錄底下找到所有檔名開頭是a且副檔名是.txt的檔案 ``` >Output >> ['D:\\vitas\\a1.txt', 'D:\\vitas\\a2.txt', 'D:\\vitas\\a3.txt'] ```python= glob.glob("D:\\vitas\\[a-c]*.txt") # 在D:\vitas\目錄底下找到所有檔名開頭是a到c且副檔名是.txt的檔案 ``` >Output >> ['D:\\vitas\\a1.txt', 'D:\\vitas\\a2.txt', 'D:\\vitas\\a3.txt', D:\\vitas\\b1.txt', 'D:\\vitas\\b2.txt'] - <span class='red'>星號(*)為萬用字元,表示任意0個以上的字元</span> - <span class='red'>[ ]表示任意在字元範圍中的任意字元,例如:[a-d]表示字元a, b, c, d</span>