一起玩Python程式:新手寫程式也可以這麼簡單!

檔案處理(上)

張傑帆

National Taiwan University

檔案處理(上)

目錄

Alt1

🎯 學習目標

今天我們要成為資料管理大師
學會如何永久保存資料!

你將學會:

  • 📂 檔案基礎:理解檔案的本質與用途
  • 🔓 開啟與關閉:安全地操作檔案
  • 📖 讀取資料:從檔案中取得資訊
  • ✍️ 寫入資料:將資料永久保存
  • 📔 日記系統:建立個人數位日記本
  • 🔍 搜尋功能:快速找到過去的記錄
  • 🎨 格式化:讓資料更有組織

準備好探索資料的祕密花園了嗎?

Let's dive into files! 🐍📁

檔案是什麼?

💾 檔案的概念

檔案就像是電腦中的一本本筆記本,可以永久保存資料!

為什麼需要檔案?

沒有檔案 有檔案
程式關閉,資料就消失了 資料永久保存
無法與其他程式共享資料 可以跨程式使用
無法回顧歷史記錄 隨時查看過去的資料

生活中的檔案例子

  • 📱 手機通訊錄:儲存聯絡人資訊
  • 📷 相簿:保存珍貴照片
  • 📝 Word文件:寫作業、報告
  • 🎵 音樂檔案:收藏喜歡的歌曲
  • 📔 日記本:記錄每天的心情

alt text

🗂️ 檔案類型

文字檔案 (Text Files)

  • 📄 可以用記事本打開
  • 內容是人類可讀的文字
  • 例如:.txt, .csv, .py, .md

二進位檔案 (Binary Files)

  • 🖼️ 需要特定程式才能開啟
  • 內容是電腦的 0 和 1
  • 例如:.jpg, .mp3, .exe, .pdf

本週重點:我們專注在文字檔案的處理!

檔案的開啟與關閉

🔓 開啟檔案:open() 函式

就像打開一本書,我們需要先「開啟」檔案才能讀寫!

基本語法

# filepath: example_code.py
file = open('檔案名稱', '模式')
# 進行檔案操作
file.close()  # 記得關閉!

📋 檔案模式一覽表

模式 說明 檔案不存在時 會覆蓋原內容嗎?
'r' 讀取模式 (Read) ❌ 錯誤 ➖ 不會
'w' 寫入模式 (Write) ✅ 建立新檔 ⚠️ 會!
'a' 附加模式 (Append) ✅ 建立新檔 ➖ 不會,加在最後
'r+' 讀寫模式 ❌ 錯誤 ⚠️ 可能會

💡 模式選擇指南

# filepath: example_code.py
# 只想讀取內容 → 用 'r'
file = open('diary.txt', 'r')

# 要寫入新內容,舊的可以刪除 → 用 'w'
file = open('diary.txt', 'w')

# 要在檔案最後面新增內容 → 用 'a'
file = open('diary.txt', 'a')

⚠️ 為什麼一定要關閉檔案?

不關閉檔案的問題:

  1. 🔒 資源佔用:檔案被鎖住,其他程式無法使用
  2. 💾 資料遺失:寫入的資料可能沒有真正存到硬碟
  3. 🐛 記憶體洩漏:程式佔用越來越多記憶體

❌ 不好的做法

# filepath: example_code.py
file = open('diary.txt', 'r')
content = file.read()
# 忘記關閉檔案!糟糕!

✅ 好的做法

# filepath: example_code.py
file = open('diary.txt', 'r')
content = file.read()
file.close()  # 記得關閉

🛡️ with 語法:自動安全關閉

with 是 Python 的魔法語法,檔案會自動關閉!

語法結構

# filepath: example_code.py
with open('檔案名稱', '模式') as 變數名稱:
    # 在這裡操作檔案
    # 程式區塊結束後,檔案自動關閉!

🌟 with 的優點

# filepath: example_code.py
# 傳統方式:要記得關閉
file = open('diary.txt', 'r')
try:
    content = file.read()
finally:
    file.close()

# with 方式:自動關閉,更簡潔!
with open('diary.txt', 'r') as file:
    content = file.read()
# 這裡檔案已經自動關閉了

🎯 實際範例

# filepath: example_code.py
# 讀取日記
with open('my_diary.txt', 'r', encoding='utf-8') as diary:
    today_entry = diary.read()
    print(today_entry)

# 寫入新日記
with open('my_diary.txt', 'a', encoding='utf-8') as diary:
    diary.write('\n2024-01-15: 今天學會了檔案處理!')

注意encoding='utf-8' 確保中文正確顯示!

檔案讀取方法

📖 三種讀取方法

Python 提供三種方式讀取檔案內容:

方法 功能 回傳類型 適用情境
read() 讀取全部內容 字串 小檔案
readline() 讀取一行 字串 逐行處理
readlines() 讀取所有行 串列 需要所有行的資料

📄 read() - 一次讀取全部

最簡單的方法,把整個檔案當作一個大字串!

# filepath: example_code.py
with open('diary.txt', 'r', encoding='utf-8') as file:
    content = file.read()
    print(content)
    print(f'檔案共有 {len(content)} 個字元')

📝 read(size) - 讀取指定字元數

# filepath: example_code.py
with open('diary.txt', 'r', encoding='utf-8') as file:
    # 讀取前 100 個字元
    first_part = file.read(100)
    print(first_part)
    
    # 繼續讀取接下來的 100 個字元
    second_part = file.read(100)
    print(second_part)

📋 readline() - 逐行讀取

每次呼叫讀取一行,適合處理大檔案!

# filepath: example_code.py
with open('diary.txt', 'r', encoding='utf-8') as file:
    line1 = file.readline()  # 讀第一行
    line2 = file.readline()  # 讀第二行
    line3 = file.readline()  # 讀第三行
    
    print('第一行:', line1)
    print('第二行:', line2)
    print('第三行:', line3)

🔄 用迴圈讀取所有行

# filepath: example_code.py
with open('diary.txt', 'r', encoding='utf-8') as file:
    line_number = 1
    while True:
        line = file.readline()
        if not line:  # 讀到檔案結尾
            break
        print(f'第 {line_number} 行: {line.strip()}')
        line_number += 1

📚 readlines() - 讀取所有行成串列

把每一行當作串列的元素!

# filepath: example_code.py
with open('diary.txt', 'r', encoding='utf-8') as file:
    lines = file.readlines()
    
print(f'檔案共有 {len(lines)} 行')
print('所有行:', lines)

# 處理每一行
for i, line in enumerate(lines, 1):
    print(f'第 {i} 行: {line.strip()}')

🎯 三種方法比較範例

假設 diary.txt 內容為:

2024-01-13: 今天天氣很好
2024-01-14: 學習Python很有趣
2024-01-15: 完成了作業
# filepath: example_code.py
# 方法1: read()
with open('diary.txt', 'r', encoding='utf-8') as file:
    content = file.read()
    print(type(content))  # <class 'str'>
    print(repr(content))  # '2024-01-13: 今天天氣很好\n2024-01-14...'

# 方法2: readline()
with open('diary.txt', 'r', encoding='utf-8') as file:
    line = file.readline()
    print(type(line))  # <class 'str'>
    print(repr(line))  # '2024-01-13: 今天天氣很好\n'
# filepath: example_code.py
# 方法3: readlines()
with open('diary.txt', 'r', encoding='utf-8') as file:
    lines = file.readlines()
    print(type(lines))  # <class 'list'>
    print(lines)  # ['2024-01-13: 今天天氣很好\n', ...]

💡 選擇方法的建議

# filepath: example_code.py
# 小檔案 (< 1MB):用 read()
with open('small_file.txt', 'r') as f:
    content = f.read()

# 大檔案:用 readline() 或迴圈
with open('big_file.txt', 'r') as f:
    for line in f:  # 最省記憶體的方式!
        process(line)

# 需要所有行的串列:用 readlines()
with open('data.txt', 'r') as f:
    lines = f.readlines()
    sorted_lines = sorted(lines)

小練習 1

🎮 小練習 1:讀取日記

任務說明

請建立一個名為 my_diary.txt 的文字檔,內容如下:

2024-01-13: 今天是美好的一天,學會了變數和資料型態!
2024-01-14: 今天學習了條件判斷,if-else 好有趣!
2024-01-15: 今天認識了迴圈,程式可以重複執行了!
  • 功能一:讀取並顯示整個日記內容

    • 使用 read() 方法
    • 提示:記得使用 with 語法和 encoding='utf-8'
  • 功能二:只顯示第一行日記

    • 使用 readline() 方法
  • 功能三:計算日記總共有幾行

    • 使用 readlines() 方法
    • 提示:使用 len() 函式
  • 功能四:顯示包含「學習」關鍵字的日記

    • for 迴圈和 in 運算子

✅ 參考寫法

# filepath: practice1_solution.py
# 功能一
with open('my_diary.txt', 'r', encoding='utf-8') as file:
    content = file.read()
    print('=== 完整日記 ===')
    print(content)

# 功能二
with open('my_diary.txt', 'r', encoding='utf-8') as file:
    first_line = file.readline()
    print('第一行日記:', first_line.strip())
# filepath: practice1_solution.py
# 功能三
with open('my_diary.txt', 'r', encoding='utf-8') as file:
    lines = file.readlines()
    print(f'日記共有 {len(lines)} 行')

# 功能四
with open('my_diary.txt', 'r', encoding='utf-8') as file:
    for line in file:
        if '學習' in line:
            print(line.strip())

休息時間 ☕

讓我們休息一下
準備學習檔案寫入!

檔案寫入操作

✍️ 寫入方法概覽

方法 功能 參數類型
write(string) 寫入一個字串 字串
writelines(list) 寫入多行 字串串列

重要:寫入方法不會自動換行,需要手動加上 \n

📝 write() - 寫入字串

基本用法

# filepath: example_code.py
# 模式 'w':覆蓋原有內容
with open('output.txt', 'w', encoding='utf-8') as file:
    file.write('這是第一行\n')
    file.write('這是第二行\n')
    file.write('這是第三行\n')

⚠️ 模式 'w' vs 'a' 的差異

# filepath: example_code.py
# 模式 'w':每次都重新開始寫
with open('test_w.txt', 'w', encoding='utf-8') as file:
    file.write('第一次寫入\n')

with open('test_w.txt', 'w', encoding='utf-8') as file:
    file.write('第二次寫入\n')  # 第一次的內容被覆蓋了!

# 結果:檔案只有「第二次寫入」
# filepath: example_code.py
# 模式 'a':在最後面繼續寫
with open('test_a.txt', 'a', encoding='utf-8') as file:
    file.write('第一次寫入\n')

with open('test_a.txt', 'a', encoding='utf-8') as file:
    file.write('第二次寫入\n')  # 接在後面!

# 結果:檔案有「第一次寫入」和「第二次寫入」

📊 write() 回傳值

# filepath: example_code.py
with open('output.txt', 'w', encoding='utf-8') as file:
    chars_written = file.write('Hello Python!\n')
    print(f'寫入了 {chars_written} 個字元')  # 寫入了 14 個字元

📋 writelines() - 寫入多行

基本用法

# filepath: example_code.py
lines = [
    '2024-01-13: 學習Python第一天\n',
    '2024-01-14: 認識了變數和資料型態\n',
    '2024-01-15: 掌握了條件判斷\n'
]

with open('diary.txt', 'w', encoding='utf-8') as file:
    file.writelines(lines)

⚠️ 注意事項

# filepath: example_code.py
# ❌ 錯誤:沒有換行符號
lines = ['第一行', '第二行', '第三行']
with open('output.txt', 'w', encoding='utf-8') as file:
    file.writelines(lines)
# 結果:第一行第二行第三行(全部黏在一起)

# ✅ 正確:加上換行符號
lines = ['第一行\n', '第二行\n', '第三行\n']
with open('output.txt', 'w', encoding='utf-8') as file:
    file.writelines(lines)

💡 實用技巧

# filepath: example_code.py
# 方法1:用串列生成式自動加上 \n
lines = ['第一行', '第二行', '第三行']
with open('output.txt', 'w', encoding='utf-8') as file:
    file.writelines([line + '\n' for line in lines])

# 方法2:用 join() 方法
with open('output.txt', 'w', encoding='utf-8') as file:
    file.write('\n'.join(lines) + '\n')

🎨 格式化寫入

使用 f-string 格式化

# filepath: example_code.py
name = '小明'
age = 15
score = 95.5

with open('student.txt', 'w', encoding='utf-8') as file:
    file.write(f'姓名:{name}\n')
    file.write(f'年齡:{age} 歲\n')
    file.write(f'成績:{score} 分\n')

📅 日記格式化範例

# filepath: example_code.py
from datetime import datetime

def write_diary_entry(content):
    """寫入一筆日記"""
    now = datetime.now()
    date_str = now.strftime('%Y-%m-%d %H:%M:%S')
    
    with open('diary.txt', 'a', encoding='utf-8') as file:
        file.write(f'[{date_str}]\n')
        file.write(f'{content}\n')
        file.write('-' * 50 + '\n')

# 使用範例
write_diary_entry('今天學會了檔案寫入,真棒!')

📊 寫入 CSV 格式

# filepath: example_code.py
students = [
    ['姓名', '年齡', '成績'],
    ['小明', '15', '95'],
    ['小華', '16', '87'],
    ['小美', '15', '92']
]

with open('students.csv', 'w', encoding='utf-8') as file:
    for row in students:
        file.write(','.join(row) + '\n')

🔄 讀取後修改再寫入

範例:更新日記內容

# filepath: example_code.py
# 讀取原有內容
with open('diary.txt', 'r', encoding='utf-8') as file:
    lines = file.readlines()

# 修改內容(例如:加上行號)
modified_lines = []
for i, line in enumerate(lines, 1):
    modified_lines.append(f'{i}. {line}')

# 寫回檔案
with open('diary.txt', 'w', encoding='utf-8') as file:
    file.writelines(modified_lines)

日記系統實作

📔 日記系統設計

系統功能

  1. ✍️ 寫入日記:記錄今天的心情
  2. 📖 閱讀日記:查看所有日記
  3. 🔍 搜尋日記:找特定日期或關鍵字
  4. 🗑️ 清空日記:重新開始

📂 日記檔案格式

========================================
日期:2024-01-15 14:30:25
========================================
今天學會了檔案處理,覺得很有成就感!
可以永久保存資料真的很棒!

========================================
日期:2024-01-16 20:15:00
========================================
今天複習了前面的內容,對Python更熟悉了。

💻 日記系統完整程式碼

# filepath: diary_system.py
from datetime import datetime

def write_diary():
    """寫入新的日記"""
    print('\n=== 寫日記 ===')
    content = input('請輸入今天的日記內容:')
    
    now = datetime.now()
    date_str = now.strftime('%Y-%m-%d %H:%M:%S')
    
    with open('my_diary.txt', 'a', encoding='utf-8') as file:
        file.write('=' * 40 + '\n')
        file.write(f'日期:{date_str}\n')
        file.write('=' * 40 + '\n')
        file.write(f'{content}\n\n')
    
    print('✅ 日記已保存!')
# filepath: diary_system.py
def read_diary():
    """閱讀所有日記"""
    print('\n=== 我的日記本 ===')
    try:
        with open('my_diary.txt', 'r', encoding='utf-8') as file:
            content = file.read()
            if content:
                print(content)
            else:
                print('日記本是空的,快來寫第一篇日記吧!')
    except FileNotFoundError:
        print('還沒有日記檔案,請先寫一篇日記!')
# filepath: diary_system.py
def search_diary():
    """搜尋日記"""
    print('\n=== 搜尋日記 ===')
    keyword = input('請輸入要搜尋的關鍵字:')
    
    try:
        with open('my_diary.txt', 'r', encoding='utf-8') as file:
            lines = file.readlines()
            found = False
            current_entry = []
            
            for line in lines:
                current_entry.append(line)
                if line.strip() == '' and current_entry:
                    entry_text = ''.join(current_entry)
                    if keyword in entry_text:
                        print(entry_text)
                        found = True
                    current_entry = []
            
            if not found:
                print(f'沒有找到包含「{keyword}」的日記')
    except FileNotFoundError:
        print('還沒有日記檔案!')
# filepath: diary_system.py
def clear_diary():
    """清空所有日記"""
    print('\n=== 清空日記 ===')
    confirm = input('確定要刪除所有日記嗎?(yes/no):')
    if confirm.lower() == 'yes':
        with open('my_diary.txt', 'w', encoding='utf-8') as file:
            pass  # 開啟 'w' 模式但不寫入,檔案就被清空了
        print('✅ 日記已清空')
    else:
        print('❌ 取消清空')
# filepath: diary_system.py
def show_menu():
    """顯示選單"""
    print('\n' + '=' * 40)
    print('📔 歡迎使用個人日記系統')
    print('=' * 40)
    print('1. ✍  寫新日記')
    print('2. 📖 閱讀所有日記')
    print('3. 🔍 搜尋日記')
    print('4. 🗑  清空日記')
    print('5. 👋 離開系統')
    print('=' * 40)
# filepath: diary_system.py
def main():
    """主程式"""
    while True:
        show_menu()
        choice = input('請選擇功能 (1-5):')
        
        if choice == '1':
            write_diary()
        elif choice == '2':
            read_diary()
        elif choice == '3':
            search_diary()
        elif choice == '4':
            clear_diary()
        elif choice == '5':
            print('👋 謝謝使用,再見!')
            break
        else:
            print('❌ 無效的選擇,請輸入 1-5')

if __name__ == '__main__':
    main()

🎯 程式設計重點

1. 錯誤處理

# filepath: example_code.py
try:
    with open('diary.txt', 'r') as file:
        content = file.read()
except FileNotFoundError:
    print('檔案不存在!')

2. 使用者友善的提示

# filepath: example_code.py
print('✅ 成功!')  # 綠色勾勾
print('❌ 錯誤!')  # 紅色叉叉
print('⚠  警告!')  # 黃色警告

3. 函式化設計

  • 每個功能獨立成一個函式
  • 主程式只負責控制流程
  • 容易維護和擴充

🧠 運算思維總整理

1️⃣ 抽象化 (Abstraction)

檔案的抽象概念

  • 檔案是「永久儲存資料的容器」
  • 不需要知道硬碟如何運作
  • 只需要知道「開啟→操作(讀/加/寫)→關閉」的流程
# filepath: example_code.py
# 抽象化:把複雜的檔案操作包裝成簡單的函式
def save_data(data, filename):
    """抽象化的儲存函式"""
    with open(filename, 'w', encoding='utf-8') as file:
        file.write(data)

def load_data(filename):
    """抽象化的讀取函式"""
    with open(filename, 'r', encoding='utf-8') as file:
        return file.read()

# 使用時很簡單
save_data('Hello!', 'test.txt')
content = load_data('test.txt')

2️⃣ 演算法思維 (Algorithmic Thinking)

安全的檔案處理流程

  1. 檢查:檔案是否存在?
  2. 開啟:用正確的模式開啟
  3. 操作:讀取或寫入
  4. 關閉:確保資源釋放
  5. 錯誤處理:處理可能的問題

3️⃣ 問題分解 (Decomposition)

日記系統的分解

日記系統
├── 寫入功能
│   ├── 取得使用者輸入
│   ├── 格式化日期時間
│   └── 寫入檔案
├── 讀取功能
│   ├── 開啟檔案
│   ├── 讀取內容
│   └── 顯示結果
└── 搜尋功能
    ├── 取得搜尋關鍵字
    ├── 逐行比對
    └── 顯示符合的結果

本週總結 🎉

🎓 你學會了什麼?

1. 檔案基礎概念

  • ✅ 理解檔案的本質與用途
  • ✅ 區分文字檔案與二進位檔案
  • ✅ 了解為什麼需要檔案處理

2. 檔案操作技能

  • ✅ 使用 open() 開啟檔案
  • ✅ 選擇正確的檔案模式 (r, w, a)
  • ✅ 使用 with 語法自動關閉檔案
  • ✅ 掌握三種讀取方法 (read, readline, readlines)
  • ✅ 掌握兩種寫入方法 (write, writelines)

3. 實務應用

  • ✅ 建立個人日記系統
  • ✅ 實作搜尋功能
  • ✅ 處理檔案錯誤
  • ✅ 格式化輸出

📊 知識地圖

檔案處理
├── 基礎概念
│   ├── 檔案類型
│   ├── 檔案路徑
│   └── 編碼問題
├── 檔案開啟
│   ├── open() 函式
│   ├── 檔案模式
│   └── with 語法
├── 檔案讀取
│   ├── read()
│   ├── readline()
│   └── readlines()
└── 檔案寫入
    ├── write()
    └── writelines()

🎯 重點回顧

概念 重點
檔案模式 r=讀取, w=覆蓋寫入, a=附加寫入
with 語法 自動關閉檔案,避免資源洩漏
encoding 處理中文必須加 encoding='utf-8'
換行符號 寫入時要手動加 \n
錯誤處理 使用 try-except 處理 FileNotFoundError

💡 最佳實踐

# filepath: best_practices.py
# ✅ 推薦的檔案處理模式

# 1. 使用 with 語法
with open('file.txt', 'r', encoding='utf-8') as file:
    content = file.read()

# 2. 錯誤處理
try:
    with open('file.txt', 'r', encoding='utf-8') as file:
        content = file.read()
except FileNotFoundError:
    print('檔案不存在')

# 3. 大檔案處理:逐行讀取
with open('big_file.txt', 'r', encoding='utf-8') as file:
    for line in file:
        process(line)

作業 📝

📝 作業說明

請選擇以下三個選項中的任一個完成:

  • 選項一適合初學者打好基礎
  • 選項二適合想要多練習的同學
  • 選項三適合想要挑戰創意的同學

繳交方式:將程式碼和執行結果截圖一起繳交

✏️ 選項一:基礎練習

作業 1:課程筆記系統

建立一個課程筆記系統,包含以下功能:

# filepath: homework1_1.py
# 1. 新增筆記:輸入課程名稱和筆記內容
# 2. 查看所有筆記
# 3. 搜尋特定課程的筆記
# 4. 計算總共記了幾堂課的筆記

# 提示:筆記格式
# ================================
# 課程:Python程式設計
# 日期:2024-01-15
# ================================
# 今天學習了檔案處理...

🔧 選項二:進階應用

作業 2:待辦事項管理系統

建立一個功能完整的待辦事項系統:

# filepath: homework2_1.py
# 必要功能:
# 1. 新增待辦事項(包含標題、內容、優先順序)
# 2. 查看所有待辦事項
# 3. 標記完成
# 4. 刪除待辦事項
# 5. 依優先順序排序顯示

# 檔案格式範例:
# [未完成][高]完成Python作業
# 內容:要完成檔案處理的作業
# 建立時間:2024-01-15 10:00:00
# ---

🚀 選項三:創意發揮

作業 3:自由專題

設計並實作一個你自己想做的檔案應用系統!

必須包含

  1. 至少 5 個功能
  2. 檔案讀取和寫入
  3. 搜尋或統計功能
  4. 良好的錯誤處理
  5. 使用者友善的介面

創意主題建議

  • 📚 閱讀筆記系統(記錄讀過的書和心得)
  • 💰 記帳系統(收入支出管理)
  • 🎵 歌單管理系統
  • 🍳 食譜收藏系統
  • 🎯 目標追蹤系統
  • 💭 名言佳句收藏
  • 📝 部落格文章管理
  • 🎮 遊戲紀錄系統

💡 作業提示

常見問題解決

# filepath: homework_tips.py
# 問題1:檔案不存在怎麼辦?
try:
    with open('file.txt', 'r') as f:
        content = f.read()
except FileNotFoundError:
    print('檔案不存在,建立新檔案')
    with open('file.txt', 'w') as f:
        f.write('')

# 問題2:如何判斷檔案是否為空?
with open('file.txt', 'r') as f:
    content = f.read()
    if not content:
        print('檔案是空的')
# filepath: homework_tips.py
# 問題3:如何在檔案中搜尋?
search_word = '關鍵字'
with open('file.txt', 'r', encoding='utf-8') as f:
    for line_num, line in enumerate(f, 1):
        if search_word in line:
            print(f'第 {line_num} 行: {line.strip()}')

# 問題4:如何修改檔案內容?
# 方法:讀取→修改→寫回
with open('file.txt', 'r', encoding='utf-8') as f:
    lines = f.readlines()

# 修改內容
modified_lines = [line.replace('舊', '新') for line in lines]

with open('file.txt', 'w', encoding='utf-8') as f:
    f.writelines(modified_lines)

🐛 常見錯誤與除錯

錯誤 1:忘記關閉檔案

# filepath: common_errors.py
# ❌ 錯誤
file = open('test.txt', 'r')
content = file.read()
# 忘記 file.close()

# ✅ 正確
with open('test.txt', 'r') as file:
    content = file.read()
# 自動關閉

錯誤 2:編碼問題

# filepath: common_errors.py
# ❌ 可能出現亂碼
with open('test.txt', 'r') as file:
    content = file.read()

# ✅ 指定 UTF-8 編碼
with open('test.txt', 'r', encoding='utf-8') as file:
    content = file.read()

錯誤 3:寫入時忘記換行

# filepath: common_errors.py
# ❌ 結果:ABC(全部黏在一起)
with open('test.txt', 'w') as file:
    file.write('A')
    file.write('B')
    file.write('C')

# ✅ 結果:A B C(各自一行)
with open('test.txt', 'w') as file:
    file.write('A\n')
    file.write('B\n')
    file.write('C\n')

錯誤 4:模式選擇錯誤

# filepath: common_errors.py
# ❌ 想要新增內容卻用了 'w'(原內容會消失!)
with open('diary.txt', 'w') as file:
    file.write('新的一天\n')

# ✅ 使用 'a' 模式附加內容
with open('diary.txt', 'a') as file:
    file.write('新的一天\n')

再次感謝!

下週見!👋

Made changes.

-----------------------------------------

圖片放大特效

table樣式

![Alt1](../images/1200px-National_Taiwan_University_logo.svg.png)![Alt2](../images/Python-logo-notext.svg.png) <style scoped> img[alt="Alt1"]{ background: rgba(255, 255, 255, 0); position: absolute; top: 10%; left: 10%; /* transform: translate(-50%, -50%); */ width: 200px; /* 調整圖片寬度 */ height: auto; /* 保持原始比例 */ padding:0; margin:0; z-index: 1; } img[alt="Alt2"]{ background: rgba(255, 255, 255, 0); position: absolute; top: 10%; left: 75%; /* transform: translate(-50%, -50%); */ width: 200px; /* 調整圖片寬度 */ height: auto; /* 保持原始比例 */ padding:0; margin:0; z-index: 2; } </style>

- [學習目標](#學習目標)

- [日記系統實作](#日記系統實作)

- [運算思維總整理](#運算思維總整理)

- [本週總結](#本週總結)

Python 主要處理兩種檔案:

### 練習要求

--- # 小練習 2 ![bg left:40%](image-9.png) --- ## 🎮 小練習 2:完整日記系統 ### 任務說明 擴充我們的日記系統,增加以下功能: --- **練習 2-1**:統計功能 - 顯示日記總數 - 顯示總字數 - 找出最長的日記 ```python # filepath: practice2_1.py def diary_statistics(): """顯示日記統計資訊""" # 請完成這個函式 pass ``` --- **練習 2-2**:分類功能 - 為日記加上心情標籤(開心、難過、平淡) - 可以按心情搜尋日記 ```python # filepath: practice2_2.py def write_diary_with_mood(): """寫日記時加上心情標籤""" # 提示:在日記中加入「心情:開心」這樣的標記 pass def search_by_mood(mood): """依心情搜尋日記""" pass ``` --- **練習 2-3**:匯出功能 - 將日記匯出為 HTML 格式 - 可以用瀏覽器開啟查看 ```python # filepath: practice2_3.py def export_to_html(): """將日記匯出為 HTML 檔案""" # 提示:HTML 基本結構 # <html><body><h1>標題</h1><p>內容</p></body></html> pass ``` --- ### ✅ 參考解答 ```python # filepath: practice2_solution.py def diary_statistics(): """顯示日記統計資訊""" try: with open('my_diary.txt', 'r', encoding='utf-8') as file: content = file.read() entries = content.split('=' * 40) # 過濾空白項目 entries = [e for e in entries if e.strip()] total_entries = len(entries) // 2 # 每篇日記有兩條分隔線 total_chars = len(content) print(f'📊 日記統計') print(f'總篇數:{total_entries} 篇') print(f'總字數:{total_chars} 字') except FileNotFoundError: print('還沒有日記!') ``` --- ```python # filepath: practice2_solution.py def write_diary_with_mood(): """寫日記時加上心情標籤""" print('\n=== 寫日記 ===') print('選擇今天的心情:') print('1. 😊 開心') print('2. 😢 難過') print('3. 😐 平淡') mood_choice = input('請選擇 (1-3):') moods = {'1': '開心😊', '2': '難過😢', '3': '平淡😐'} mood = moods.get(mood_choice, '平淡😐') content = input('請輸入今天的日記內容:') now = datetime.now() date_str = now.strftime('%Y-%m-%d %H:%M:%S') ``` --- ```python # filepath: practice2_solution.py with open('my_diary.txt', 'a', encoding='utf-8') as file: file.write('=' * 40 + '\n') file.write(f'日期:{date_str}\n') file.write(f'心情:{mood}\n') file.write('=' * 40 + '\n') file.write(f'{content}\n\n') print('✅ 日記已保存!') def search_by_mood(mood): """依心情搜尋日記""" mood_map = {'1': '開心😊', '2': '難過😢', '3': '平淡😐'} search_mood = mood_map.get(mood) ``` --- ```python # filepath: practice2_solution.py try: with open('my_diary.txt', 'r', encoding='utf-8') as file: content = file.read() entries = content.split('=' * 40) found = False for i in range(0, len(entries), 2): if i+1 < len(entries): entry = entries[i] + '=' * 40 + entries[i+1] if f'心情:{search_mood}' in entry: print(entry) found = True if not found: print(f'沒有找到心情為「{search_mood}」的日記') except FileNotFoundError: print('還沒有日記!') ``` --- ```python # filepath: practice2_solution.py def export_to_html(): """將日記匯出為 HTML 檔案""" try: with open('my_diary.txt', 'r', encoding='utf-8') as file: content = file.read() html = f''' <!DOCTYPE html> <html lang="zh-TW"> <head> <meta charset="UTF-8"> <title>我的日記本</title> <style> body {{ font-family: Arial, sans-serif; margin: 20px; }} h1 {{ color: #2c3e50; }} .entry {{ border: 2px solid #3498db; padding: 15px; margin: 20px 0; background-color: #ecf0f1; }} </style> </head> <body> <h1>📔 我的日記本</h1> <pre class="entry">{content}</pre> </body> </html> ''' ``` --- ```python # filepath: practice2_solution.py with open('my_diary.html', 'w', encoding='utf-8') as file: file.write(html) print('✅ 日記已匯出為 my_diary.html') print('可以用瀏覽器開啟查看!') except FileNotFoundError: print('還沒有日記!') ```

--- ```python # filepath: example_code.py def safe_file_operation(filename, mode, operation): """安全的檔案操作演算法""" try: # 步驟1: 開啟檔案 with open(filename, mode, encoding='utf-8') as file: # 步驟2: 執行操作 result = operation(file) # 步驟3: 自動關閉(with語法) return result except FileNotFoundError: print(f'錯誤:檔案 {filename} 不存在') return None except Exception as e: print(f'發生錯誤:{e}') return None # 使用範例 def read_operation(file): return file.read() content = safe_file_operation('data.txt', 'r', read_operation) ```

--- ```python # filepath: example_code.py # 問題分解範例:將大問題分成小函式 # 小問題1:格式化日期 def format_date(): from datetime import datetime return datetime.now().strftime('%Y-%m-%d %H:%M:%S') # 小問題2:格式化日記項目 def format_entry(date, content): return f'=' * 40 + f'\n日期:{date}\n' + '=' * 40 + f'\n{content}\n\n' # 小問題3:寫入檔案 def append_to_file(filename, content): with open(filename, 'a', encoding='utf-8') as file: file.write(content) ``` --- ```python # filepath: example_code.py # 組合小問題解決大問題 def write_diary_entry(content): """組合所有小函式完成寫日記功能""" date = format_date() entry = format_entry(date, content) append_to_file('diary.txt', entry) print('✅ 日記已保存!') # 使用 write_diary_entry('今天學會了問題分解!') ```

--- ### 🎯 運算思維實踐 **在日記系統中的應用** | 運算思維 | 在日記系統中的體現 | |----------|-------------------| | 抽象化 | 將檔案視為資料容器,不關心底層實作 | | 演算法思維 | 設計安全的檔案操作流程 | | 問題分解 | 將系統分成寫入、讀取、搜尋等模組 | | 模式識別 | 識別日記的共同格式(日期+內容) |

--- #### 作業 1-2:單字本系統 (30%) 製作一個英文單字本,可以記錄單字和中文意思: ```python # filepath: homework1_2.py # 1. 新增單字:輸入英文單字和中文意思 # 2. 查看所有單字 # 3. 隨機測驗:隨機顯示一個單字,請使用者輸入中文 # 4. 統計單字數量 # 檔案格式範例 (words.txt) # apple=蘋果 # banana=香蕉 # computer=電腦 ``` --- #### 作業 1-3:檔案讀寫測驗 (30%) 回答以下問題並寫出程式碼: ```python # filepath: homework1_3.py # 問題1:為什麼要使用 with 語法?(10%) # 回答: # 問題2:寫出一個程式,讀取 data.txt 並:(20%) # - 計算檔案有幾行 # - 計算檔案有幾個字 # - 找出最長的一行 ```

--- #### 作業 2-2:學生成績管理系統 (50%) 製作一個成績管理系統: ```python # filepath: homework2_2.py # 必要功能: # 1. 新增學生成績(姓名、科目、分數) # 2. 查詢某位學生的所有成績 # 3. 計算某位學生的平均分數 # 4. 找出某科目的最高分和最低分 # 5. 產生成績報表(存成 report.txt) # 提示:可以使用 CSV 格式 # 姓名,科目,分數 # 小明,數學,95 # 小明,英文,87 ```

**評分標準**: - 創意性 (30%) - 功能完整性 (30%) - 程式品質 (20%) - 使用者體驗 (20%)

--- ### 📤 繳交規定 1. **檔案命名**:`學號_姓名_week12.py` 2. **程式碼要求**: - 每個函式都要有註解說明 - 變數命名要有意義 - 適當的錯誤處理 3. **測試資料**: - 附上測試用的資料檔案 - 或在程式中說明如何建立測試資料 --- 4. **執行結果**: - 擷取程式執行的畫面 - 展示各個功能的運作 5. **繳交期限**:下週上課前 **加分項目**: - 程式有完善的使用說明 - 有創意的功能設計 - 優秀的使用者介面

--- ### 🎓 學習資源 **推薦閱讀**: - Python 官方文件:檔案 I/O - 《Python 程式設計入門》第 8 章 - 線上教學影片:檔案處理基礎 **練習平台**: - LeetCode:檔案相關題目 - HackerRank:File Handling 專區 --- 下週預告: ## Week 13: 檔案處理(下) - 進階技巧與應用 - JSON 檔案處理 - CSV 檔案處理 - 檔案與資料夾操作 - 實作通訊錄系統 期待與你們一起繼續學習!🚀

--- # 謝謝大家!👏 ### 有問題隨時發問! ### 記得完成作業喔!📝

備用頁面:常見錯誤