檔案及目錄

      在〈檔案及目錄〉中尚無留言

IO

Input/Output 為電腦重要的處理機制. 記憶体中的資料若要傳送到網路, 磁碟等裝置, 就必需啟動I/O機制傳輸.

同步IO

CPU因處理速度比起I/O傳輸還要快上千倍萬倍, 如果在傳送期間, CPU進入等待狀態, 待傳輸完畢後, 才處理後續的指令, 稱為同步IO. 這種狀況想當然爾, 整個系統會停頓下來卡住不動.

異步IO

IO傳輸期間, CPU不等待, 繼續執行後面的指令, 待IO完成後再回來處理IO這部份的收尾工作, 這種方式稱為異步IO. 當然這種方式系統不會停頓, 但會加重程式的複雜度. 比如, IO要如何通知CPU已處理完畢了, 這就夠複雜了.

檔案存取

存取檔案, 注意如下幾點
1. 使用open()函數開啟一個檔案物件 : file
2. file.read() 讀取整個檔案的內容, 並傳回一整個字串 str
3. 開啟檔案, 操作檔案時, 都可能會發生IOError 例外, 所以最好用try-except包含起來
4. 檔案存取完畢, 需進行file.close(), 否則檔案會發生損毀且無法修復. 但如果把close()寫在try區塊, 則可能開啟正常, 但寫入錯誤而跳到except, 然後就無法執行close(), 所以close()一定要寫在finally區塊
5. finally區塊是不論有沒有例外都會執行的. 如果open()時就錯誤, 那到了finally時會因為file沒有定義, 所以close()又會發生錯誤, 因此需先判斷 file是否定義過了. if ‘file’ in locals().keys()即為判定是否有定義file. 請注意, ‘file’ 需當成字串, 用單引號包含住

try:
    file=open('d:/test.txt', 'r');
    str=file.read();
    print(str)
except IOError as e:
    print(e)
finally:
    if 'file' in locals().keys():
        file.close();
        print('已關閉檔案')

 with open() as file

每次關檔都要用finally, 實在太煩人了, 所以可以使用 with open() as file, 這樣系統就會幫我們處理close()的事了. 請注意, 還是要用try-except處理IOError.

try:
    with open('d:/testt.txt', 'r') as file:
        print(file.read())
except IOError:
    pass

read(size)

read()會把整個檔案讀進來的, 如果檔案爆大, 那記憶体就不夠用. 所以可以一次只讀取size 個byte, 然後用迴圈包起來. 只不過, 怎麼知道讀到尾巴了呢, 請看下面藍色的部份, 當讀不到資料, str就是空字串, 所以用if not str:break中斷

try:
    with open('d:/test.txt', 'r') as file:
        while True:
            str=file.read(20)
            if not str: break
            print(str, end='')
except IOError as e:
    print(e)

readline()

readline()每次會讀取一行, 連同換行符號也會讀進來, 所以使用 line.strip()把 “\n”去除掉

try:
    with open('d:/test.txt', 'r') as file:
        while True:
            line=file.readline().strip()
            if not line: break
            print(line)
except IOError as e:
    print(e)

readlines()

readlines()會傳回list, 所以可以使用foreach印出. 其實也不需要使用readlines(), 使用file也可以

try:
    with open('d:/test.txt', 'r') as file:
        for line in file.readlines():
            print(line.strip())
except IOError as e:
    print(e)
try:
    with open('d:/test.txt', 'r') as file:
        for line in file:
            print(line.strip())
except IOError as e:
    print(e)

二進位檔

讀取jpg, exe等二進位檔案, 在open時使用 ‘rb’

try:
    with open('d:/school.jpg', 'rb') as file:
        str=file.read()
        print(str)
except IOError as e:
    print(e)

字元編碼

open()的第三個參數即為編碼方式

with open('d:/test.txt', 'r', encoding='ansi') as file:

寫入

開檔時, 使用 ‘w’ , ‘wb’即可, 但若檔案已存在, 則會刪掉檔案再寫入. 如果要想附加寫在檔案後面, 則使用 ‘a’ (append模式)

try:
    with open('d:/test.txt', 'a') as file:
        file.write('\n第二行')
except IOError as e:
    print(e)

建立目錄

建立資料夾需使用 os.mkdir(str)。需注意路徑的寫法為 d:/test,或者是 d:\\test。建立資料夾後,若再次執行建立,就會發生runtime error。所以在建立資料夾之前,需先檢查資料夾是否存在。

import os
path='d:/pythontest'
if not os.path.isdir(path):
os.mkdir(path)

os.mkdir()只是在上層目錄已存在時,才能建立最底層的目錄,所以如果要建立多層目錄,則需使用 os.makedirs()

刪除檔案

os.remove(file) 為刪除檔案

刪除空目錄

os.removedirs(path) 為刪除資料夾,同樣在刪除之前,需檢查目錄是否存在。另外如果目錄之下有其他子目錄或是檔案,是無法刪除的,會發生例外。

import os
path='d:/pythontest'
os.removedirs(path)

刪除非空目錄

若要將目錄及目錄下所有的檔案及子目錄一併刪除,則要使用 shutil.rmtree()。不過這個方法很恐佈喔,如果目錄的路徑一不小心指定錯誤,裏面的資料全都不見了,所以執行之前,一定要再三確認路徑是否有寫錯。

import shutil
shutil.rmtree('d:/pythontest')

列出目錄

dirs=os.listdir(path) 可傳回指定目錄下的子目錄及檔案,不過傳回值只是當下目錄或檔案的名稱而以,若要形成絕對路經,則要使用 os.path.join(path, dir)

import os
path='d:/pythontest'
dirs=os.listdir('d:/')
for dir in dirs:
print(os.path.join(path, dir))

遞迴目錄

目錄之下還有子目錄,若連同子目錄也要一併拜訪,則需使用遞迴方式。此例僅說明遞迴的重要性,在python 中盡可能不要用此法,請改用稍後會說明的 os.walk。

需注意的是,在 os.listdir(path)時,有可能因為權限不足無法拜訪而產生例外,所以需在 os.listdir前後,使用try-except包含起來。

import os
tree=[]
def dirTree(path):
try:
dirs=os.listdir(path)
for dir in dirs:
abs=os.path.join(path, dir)
if os.path.isdir(abs):
tree.append(abs)
dirTree(abs)
except:
pass
dirTree('d:/pictures')
for dir in tree:
print(dir)

os.walk

os.walk(path) 會把 path之下的所有子目錄及檔案列出。os.walk 是使用 c語言寫出的,所以效能上,比上述的遞迴快很多。

tree=os.walk('d:/pictures')
for dirs in tree:
print(dirs)

上述每一個dirs 的格式如下 (當前絕對路徑, [子目錄] , [檔案] ) 。

所以如果要把目前目錄下所有的子目錄列出,可用如下代碼

tree=os.walk('d:/pictures')
for root, subdirrs, files in tree:
print(root)

copy檔案

使用os的擴充模組 shutil, 裏面就有copyfile()

import shutil
shutil.copyfile('d:/3.docx', 'd:/文件.docx')

os.path.join

將二個路徑結合在一起,如下

path1="d:/testdir"
path2="tiger.jpg"
path3=os.path.join(path1, path2)
print(path3)

結果 :
d:/testdir/tiger.jpg

os.path.dirname/os.path.basename

取得路徑名及檔案名

path="d:/testdir/tiger.jpg"
print(os.path.dirname(path))
print(os.path.basename(path))

結果:
d:/testdir
tiger.jpg

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *