Python 檔案處理 (File Handling)

Python 提供內建的函數來讀取、寫入和操作檔案。

開啟檔案

使用 open() 函數開啟檔案:

file = open("filename.txt", "mode")

檔案模式

模式說明
r讀取(預設)
w寫入(會覆蓋原檔案)
a附加(在檔案尾端寫入)
x建立(如果檔案已存在會報錯)
r+讀取和寫入
b二進制模式(可與其他模式組合,如 rb
t文字模式(預設,可與其他模式組合,如 rt
# 讀取模式
f = open("file.txt", "r")

# 寫入模式
f = open("file.txt", "w")

# 二進制讀取
f = open("image.png", "rb")

with 語句(推薦)

使用 with 語句會自動關閉檔案,即使發生例外:

with open("file.txt", "r") as f:
    content = f.read()
    # 使用 content
# 檔案會自動關閉

相比傳統方式:

# 傳統方式(需要手動關閉)
f = open("file.txt", "r")
try:
    content = f.read()
finally:
    f.close()

讀取檔案

read() - 讀取全部內容

with open("file.txt", "r") as f:
    content = f.read()
    print(content)

read(n) - 讀取 n 個字元

with open("file.txt", "r") as f:
    chunk = f.read(100)  # 讀取前 100 個字元
    print(chunk)

readline() - 讀取一行

with open("file.txt", "r") as f:
    line1 = f.readline()
    line2 = f.readline()
    print(line1)
    print(line2)

readlines() - 讀取所有行

with open("file.txt", "r") as f:
    lines = f.readlines()  # 回傳 list
    for line in lines:
        print(line, end="")  # line 已經包含換行符號

逐行讀取(推薦用於大檔案)

with open("file.txt", "r") as f:
    for line in f:
        print(line, end="")

寫入檔案

write() - 寫入字串

with open("file.txt", "w") as f:
    f.write("Hello, World!\n")
    f.write("Python is awesome!")
使用 w 模式會覆蓋檔案原有的內容!

writelines() - 寫入多行

lines = ["Line 1\n", "Line 2\n", "Line 3\n"]

with open("file.txt", "w") as f:
    f.writelines(lines)

附加內容

with open("file.txt", "a") as f:
    f.write("This is appended.\n")

檔案位置

tell() - 取得目前位置

with open("file.txt", "r") as f:
    print(f.tell())  # 0
    f.read(5)
    print(f.tell())  # 5

seek() - 移動位置

with open("file.txt", "r") as f:
    f.seek(10)  # 移動到第 10 個位元組
    content = f.read()
    print(content)

檔案資訊

with open("file.txt", "r") as f:
    print(f.name)      # 檔案名稱
    print(f.mode)      # 開啟模式
    print(f.closed)    # 是否已關閉

編碼

指定檔案編碼(預設是系統編碼):

# 讀取 UTF-8 編碼的檔案
with open("file.txt", "r", encoding="utf-8") as f:
    content = f.read()

# 寫入 UTF-8 編碼的檔案
with open("file.txt", "w", encoding="utf-8") as f:
    f.write("你好,世界!")

二進制檔案

# 讀取二進制檔案
with open("image.png", "rb") as f:
    data = f.read()

# 寫入二進制檔案
with open("copy.png", "wb") as f:
    f.write(data)

# 複製檔案
with open("source.png", "rb") as src:
    with open("dest.png", "wb") as dst:
        dst.write(src.read())

檔案和目錄操作

使用 os 模組:

import os

# 檢查檔案/目錄是否存在
print(os.path.exists("file.txt"))

# 檢查是否為檔案
print(os.path.isfile("file.txt"))

# 檢查是否為目錄
print(os.path.isdir("folder"))

# 取得檔案大小
print(os.path.getsize("file.txt"))

# 刪除檔案
os.remove("file.txt")

# 重新命名檔案
os.rename("old.txt", "new.txt")

# 取得目前目錄
print(os.getcwd())

# 改變目前目錄
os.chdir("/path/to/directory")

# 列出目錄內容
print(os.listdir("."))

# 建立目錄
os.mkdir("new_folder")

# 建立多層目錄
os.makedirs("path/to/folder")

# 刪除目錄
os.rmdir("empty_folder")

使用 pathlib(推薦)

pathlib 提供物件導向的路徑操作:

from pathlib import Path

# 建立 Path 物件
p = Path("folder/file.txt")

# 檢查是否存在
print(p.exists())

# 讀取檔案
content = p.read_text()
content = p.read_bytes()

# 寫入檔案
p.write_text("Hello, World!")
p.write_bytes(b"binary data")

# 取得檔案資訊
print(p.name)      # file.txt
print(p.stem)      # file
print(p.suffix)    # .txt
print(p.parent)    # folder

# 列出目錄
for item in Path(".").iterdir():
    print(item)

# 搜尋檔案
for txt_file in Path(".").glob("*.txt"):
    print(txt_file)

# 遞迴搜尋
for py_file in Path(".").rglob("*.py"):
    print(py_file)

實際範例

逐行處理大檔案

def process_large_file(filename):
    with open(filename, "r", encoding="utf-8") as f:
        for line_number, line in enumerate(f, 1):
            # 處理每一行
            processed = line.strip().upper()
            print(f"{line_number}: {processed}")

process_large_file("data.txt")

複製檔案

def copy_file(src, dst, chunk_size=8192):
    with open(src, "rb") as f_src:
        with open(dst, "wb") as f_dst:
            while True:
                chunk = f_src.read(chunk_size)
                if not chunk:
                    break
                f_dst.write(chunk)

copy_file("source.bin", "dest.bin")

搜尋檔案內容

def search_in_file(filename, keyword):
    results = []
    with open(filename, "r", encoding="utf-8") as f:
        for line_number, line in enumerate(f, 1):
            if keyword in line:
                results.append((line_number, line.strip()))
    return results

matches = search_in_file("log.txt", "ERROR")
for line_num, line in matches:
    print(f"Line {line_num}: {line}")

統計檔案

from pathlib import Path

def file_stats(filename):
    p = Path(filename)
    content = p.read_text(encoding="utf-8")
    
    lines = content.split("\n")
    words = content.split()
    chars = len(content)
    
    return {
        "lines": len(lines),
        "words": len(words),
        "characters": chars
    }

stats = file_stats("document.txt")
print(f"Lines: {stats['lines']}")
print(f"Words: {stats['words']}")
print(f"Characters: {stats['characters']}")