iT邦幫忙

2025 iThome 鐵人賽

DAY 26
0

前言:為什麼要學「檔案處理」?

寫程式一開始,我們的世界都很「短暫」
變數一跑完就消失、輸出一印完就沒了!

但真正的應用不是這樣的。

你可能想要記錄使用者登入紀錄、分析一堆資料、保存遊戲進度、
或把 AI 結果匯出成 CSV 報表...等

這些都需要「檔案處理(File Handling)」。

學會它,代表你能讓程式:

  • 記得上次的結果,
  • 載入外部資料,
  • 寫出報告、報表、設定檔,
  • 並且安全地管理資源,不會因為沒關檔而出錯。

本篇會從最基礎的 open()read()write() 開始,
一路帶你掌握 文字檔、CSV、DictWriter、seek/tell 等常見操作,
再搭配實作練習,讓你不只是「會開檔」,而是真正懂得如何和外部世界對話的工程師。

ㄧ、檔案存取基礎

那我們就先從「開起檔案」說明吧!

open() 的基本用法與回傳:

f = open(file, mode='r', buffering=-1, encoding=None, ...)

光是這一行code,我們就有很多重點可以來介紹!一起來看看!

  • file:檔名(可以是相對路徑或絕對路徑)。
  • mode:開啟檔案模式。最重要的參數(決定讀、寫、追加、二進位等)。下方會詳細說明。
  • encoding:文字編碼(預設在 Windows 可能是 cp950;建議明確指定 encoding='utf-8')。常用的編碼字串:ascii,big5,utf8

buffering

  • 0:不緩衝(binary mode only)
  • 1:行緩衝(newline based)
  • >1:指定緩衝區大小(bytes)
  • 1(預設):依系統預設

我們這邊來介紹一下mode的種類:(很重要!)

  • 'r':讀取(預設)。檔案不存在會噴錯。
  • 'w':寫入(覆蓋原檔)。若檔案不存在會建立新檔。
  • 'a':追加(append)。內容會接在檔尾。
  • 'x':建立新檔(若檔已存在則失敗)。
  • '+':更新(可讀可寫,結合上面某種模式,例如 'r+')。
  • 加上 'b' 即為二進位模式(例如 'rb''wb')。

範例:open('data.txt', 'w', encoding='utf-8')

二、讀檔方法:讓程式「讀懂」檔案

假設 f = open('file.txt', 'r', encoding='utf-8')

  • f.read(size=-1):讀取 size 個字元(size 預設 -1 表示讀完整個檔案)。
    • 適合小檔案一次讀完。大型檔案不建議一次全讀以免吃光記憶體。
  • f.readline(size=-1):讀到換行(包含換行符)或 EOF,回傳單行字串。size 可限制最多讀多少字元。
  • f.readlines():把檔案每行放到 list 回傳(每個元素含換行符)。
  • 迭代檔案:for line in f: —— 這是最常用、記憶體友善的逐行讀法

範例:
在做範例之前,要先去創建一個.txt檔案
https://ithelp.ithome.com.tw/upload/images/20251010/20164721HSq1qVOqzs.png

創好之後,再執行以下程式碼:
這邊做個小提醒,如果怕程式找不到檔案,可以先用絕對路徑!

filename = input('請輸入讀取檔名:')

fin = open(filename)
line = fin.readline()

while line:
    print(line, end='')
    line = fin.readline()

輸出:

成功讀取的話,就會看到程式把檔案內容列印出來!

https://ithelp.ithome.com.tw/upload/images/20251010/20164721uvIqAJbaq0.png

三、檔案物件:輸出資料操作

  • write(s):把字串 s 寫進檔案(傳回寫入的字元數)。注意:write 需要字串;對其他型別先 str()
  • print(..., file=f):利用 printfile 參數輸出到檔案(自動加換行,且更方便)。
  • flush():把緩衝內容立刻寫入磁碟(通常用於長時間執行、要即時寫入紀錄時)。
  • close():關閉檔案並釋放資源(若忘記呼叫,可能導致資料未寫入或檔案鎖住)。

推薦作法:使用 with open(...) as f: 可以自動關閉檔案(context manager),不需要手動 close()(文件資源管理協定:__enter__, __exit__)。

範例:

poem = '''床前明月光
疑是地上霜
舉頭望明月
低頭思故鄉
'''

try:
    print(poem, file=open('output.txt', 'w'), flush=True)
    print('資料寫出至output.txt')
except Exception as e:
    print('資料寫出失敗:', e)

輸出:
https://ithelp.ithome.com.tw/upload/images/20251010/20164721AEpnpfTDP3.png

可以到存取路徑的地方去查看有沒有成功喔!
建議路徑可以先訂在桌面(最好找!)

https://ithelp.ithome.com.tw/upload/images/20251010/20164721oMjB8vdnO6.png

假設我們要再追加內容至剛剛的檔案要如何實作呢?(利用'a')
這邊一樣建議在路徑上可以使用絕對路徑!

poem = '''故人西辭黃鶴樓
煙花三月下揚州
孤帆遠影碧空盡
惟見長江天際流
'''
try:
    with open('output.txt', 'a') as f:
        f.write(poem)
    print('資料成功新增至output.txt')
except Exception as e:
    print('資料新增失敗:', e)

https://ithelp.ithome.com.tw/upload/images/20251010/20164721u88JEbLhXF.png

成功新增內容的話,也可以實際打開檔案是否成功喔!

https://ithelp.ithome.com.tw/upload/images/20251010/20164721KamKWC1e8W.png

四、檔案讀取時的定位:tell() / seek()

  • tell():回傳目前檔案讀寫位置(以位元/字元為單位,取決於模式)。
  • seek(offset, from=0):設定檔案指標位置。from 可以是:
    • 0:從檔頭起算(預設),
    • 1:從目前位置為起點,
    • 2:從檔尾起算。
      用途:跳到檔頭、跳到檔尾或回到檔中間位置讀寫。

這邊一樣先創一個檔案(裡面的內容可以自行決定)
這邊我就打一下我很愛的雞湯語錄~

https://ithelp.ithome.com.tw/upload/images/20251010/20164721Fc6ojEInl4.png

f=open('Believe.txt', 'r')
str = f.read(32)
print ("讀取的字串是 : ", str)
position = f.tell()
print ("目前位置 : ", position)
position = f.seek(34, 0)
str = f.read(60)
print ("重新調整後讀取的字串是 : ", str)
position = f.tell()
print ("目前位置 : ", position)
f.close()

輸出:
https://ithelp.ithome.com.tw/upload/images/20251010/201647210ecQYrnxF4.png

五、CSV 檔案處理:Python 資料人的好朋友

CSV(Comma-Separated Values)= 以逗號分隔的純文字表格。
幾乎所有試算表軟體都支援(Excel、Google Sheets)。

特性:

1.純文字格式,可用記事本打開
2.每行是一筆資料(record)
3.每欄用逗號分隔(field)
4.第一行通常是欄位名稱(header)
5.可跨平台交換資料
6.若欄位含逗號/換行,需加引號包住

1.讀取csv

把每一列變成 list(記得要先import csv)

假設我們現在有一個csv檔案(data.csv):
https://ithelp.ithome.com.tw/upload/images/20251010/20164721xwebod6wWr.png

import csv

file = open('data.csv', 'r')
csvCursor = csv.reader(file)

for row in csvCursor:
    print(row)
    
file.close()

輸出:
https://ithelp.ithome.com.tw/upload/images/20251010/20164721E7cVpwKcgG.png

也可以試試看這種指定索引的方式:

import csv

file = open('data.csv', 'r')
csvCursor = csv.reader(file)

for row in csvCursor:
    print(row[0],row[1],row[2],row[3],row[4],row[5],row[6])
    
file.close()

輸出:
https://ithelp.ithome.com.tw/upload/images/20251010/20164721Bf8JEaD9mC.png

常用參數(重要!)

  • delimiter:欄位分隔符(預設 ,
  • quotechar:引用字元(預設 "
  • lineterminator:換行符(預設 \r\n
  • quoting:引用模式(csv.QUOTE_MINIMAL, csv.QUOTE_ALL, csv.QUOTE_NONNUMERIC, csv.QUOTE_NONE
  • strict:格式錯誤是否拋例外

提醒:CSV 的字元編碼要和讀取程式一致,否則 Excel/記事本打開會亂碼(特別是 Big5 / CP950 與 UTF-8 的差異)。如果是要給 Excel(繁體 Windows)打開,可能需要 encoding='cp950' 或使用 Excel 的匯入功能指定編碼。

2.使用DictReader讀取CSV檔案

csv.DictWriter:以 dict 寫入,並可 writeheader() 寫出標頭。

舉例:

csv.DictReader:把每一列變成 dict(欄位名為 key)

import csv

file = open('data.csv', 'r')
csvCursor = csv.DictReader(file)

for row in csvCursor:
    print(row['name'], row['score'])
    
file.close()

輸出:
https://ithelp.ithome.com.tw/upload/images/20251010/20164721H1ESr608oY.png

3.使用Writer物件輸出至CSV檔案

假設我要把分析結果、學生名單、銷售報表寫回 CSV!」

這時候,我們就會使用 csv.writer() 物件

語法說明:

語法 說明
open('檔名', 'w', newline='', encoding='utf-8') w 代表「寫入模式」。newline='' 可避免多出空白行。
csv.writer(f) 建立一個「寫入器(writer)」物件。
writer.writerow(可疊代物件) 寫入一行資料(list、tuple 都可以)。
writer.writerows(多筆資料) 一次寫入多行資料(傳入巢狀 list)。

範例:

import csv

with open('result.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerow(['name', 'age', 'city'])      # 寫入一行
    writer.writerow(['Alice', 20, 'Taipei'])
    writer.writerow(['Bob', 22, 'Kaohsiung'])

成功後,就可以到該儲存路徑看到結果喔!
https://ithelp.ithome.com.tw/upload/images/20251010/20164721dRZ7GHEP3d.png

範例2:

import csv

header = ['name', 'address', 'tel', 'email', 'age']
data = [['Sean', '123, Oak Street, Taipei', '02-9876-5432', 'sean@gmail.com', 40],
        ['Amy', '456, Park Avenue, Taichung', '04-8877-6655', 'amy@gmail.com', 30],
        ['David', '789 First Road Tainan', '06-654-3210', 'david@gmail.com', 25]]

file = open('contact.csv', 'w')
csvCursor = csv.writer(file)
csvCursor.writerow(header)
for d in data:
    csvCursor.writerow(d)
file.close()
print('聯絡人輸出至contact.csv')

輸出:(看到成功輸出後,就可以開啟檔案檢查!)

https://ithelp.ithome.com.tw/upload/images/20251010/20164721oYScnTSwhX.png

打開檔案可以看見成功寫入的內容:
https://ithelp.ithome.com.tw/upload/images/20251010/20164721ZfZNZch7eF.png

4.使用DictWriter物件輸出至CSV檔案

前面我們學過 csv.writer(),它是把 list 或 tuple 寫進 CSV。
但在實務中,資料往往長這樣:

students = [
    {'name': 'Alice', 'math': 88, 'english': 92},
    {'name': 'Bob', 'math': 75, 'english': 85},
    {'name': 'Cathy', 'math': 95, 'english': 98}
]

這是「字典格式」的資料(dictionary),
每一筆都是一個學生、裡面有多個欄位。

若要寫成 CSV,我們可以使用更方便的工具 —— csv.DictWriter()

語法說明:

語法 說明
csv.DictWriter(f, fieldnames=[欄位名清單]) 建立字典寫入器(key 會對應欄位名稱)
writeheader() 自動根據 fieldnames 寫出表頭
writerow(dictionary) 寫入一筆字典資料
writerows(list_of_dict) 一次寫入多筆字典資料

範例:
結合我們先前所學,我們也可以自己輸入資料,自動存成csv檔案!

import csv

fieldnames = ['product', 'price', 'stock']

with open('products.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()

    while True:
        product = input("輸入商品名稱(或輸入 q 結束):")
        if product.lower() == 'q':
            break
        price = float(input("輸入價格:"))
        stock = int(input("輸入庫存量:"))
        writer.writerow({'product': product, 'price': price, 'stock': stock})
        print("✅ 已寫入一筆資料!")

print("資料已儲存至 products.csv")

輸出:
https://ithelp.ithome.com.tw/upload/images/20251010/20164721FtKqREDRY3.png

儲存成功後,可以到該路徑查看products.csv:
https://ithelp.ithome.com.tw/upload/images/20251010/20164721MJZJo50U8q.png

新手常見錯誤:

錯誤狀況 問題說明 解法
忘記 writeheader() 結果第一列變成資料而不是欄位名。 在寫資料前一定要呼叫一次。
字典 key 跟 fieldnames 不一致 會漏掉或多出欄位。 確保所有 key 名稱與 fieldnames 完全相同。
中文亂碼 在 Windows 上開啟會變亂碼。 encoding='utf-8-sig'

結語

今天是第26天~這幾天一直在思考要怎麼把想要教給讀者的知識,
濃縮在這三天~真的好難取捨啊啊!!

每次在撰寫文章的時候,看到最底下「已輸入8000字,,,9000字,,,10000字!!」
都會覺得讀者會不會其實覺得我很撈叨?話太多!哈哈哈~
不過在這邊也真的很佩服每位鐵人們!
我自己也當過螢幕前的讀者,現在更能了解,或許讀者花不到幾分鐘就看完的文章,
我們可能耗費了3小時以上在撰寫(like me!)~

回歸正傳,

我們今天學了很多檔案處理的技巧,這其實很重要!
也對明天我們要進行的數據分析做一個預告~
學會檔案處理,就像是讓專案有「記憶」、「有延續性」,
再也不用害怕,電腦一關掉資料都不見的心痛感~

那麼我們就明天見囉!!辛苦了!!


上一篇
【Day25】程式的安全氣囊:例外處理 Exception Handling 全攻略
下一篇
【Day27】想學數據分析?先搞懂 NumPy!
系列文
Python 小白的逆襲:30 天從零到能教人的精華筆記,寫給迷惘的你與當年的我自己!27
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言