一筆資料可以跨越多個文字行
操作員在備註欄按下換行,匯出的CSV看起來多了一行,不代表多了一件產品。CSV的一筆邏輯記錄可以包含帶換行的欄位;如果程式先逐行切開,再以逗號分割,就可能把備註後半段當成下一件產品,後面的欄位也全部錯位。
先明訂交換格式:分隔符號、引號字元、欄位順序、文字編碼、標題列與記錄換行方式。本文使用逗號分隔、雙引號包覆、UTF-8及有標題列的教學格式,規則參考RFC 4180與Python csv。其他CSV方言可能不同,不能只看副檔名就假設相容。
準備三個欄位:產品編號、備註、數量。備註允許逗號、雙引號與換行,產品編號必須當文字保存。把這些限制寫入匯出與匯入規格,兩邊使用能理解CSV引號狀態的解析器,不用字串split代替。
適用於報表檔案與資料交換程式,不保證特定PLC檔案指令或HMI匯入功能能處理多行欄位。若接收設備文件限制一筆一行或不支援引號,應另訂可相容的格式並驗收,不能只因桌面程式讀得開就送入設備。
把特殊字元放進同一個欄位
範例產品A001的備註有兩行,第一行為「先檢查,再復歸」,第二行為「操作員說 "完成"」,數量為2。CSV輸出時,整個備註欄以雙引號包住;內容中的逗號不再是分隔符號,內容換行仍屬於備註。
備註內原本的每個雙引號寫成兩個連續雙引號。這與JSON常見的反斜線跳脫不同,不能把JSON字串直接貼進CSV後期待相同解析。輸入欄位交給csv.writer,讓程式庫依既定方言完成包覆與引號處理。
再加產品A002,備註為正常、數量3。檔案可能有四個實體文字行:標題一行、第一筆跨兩行、第二筆一行;解析後仍是標題加兩筆產品,每筆三欄。驗收要計邏輯記錄與欄位數,不以文字換行數當產品數。
完成讀回後,A001備註應保留逗號、原來那一個換行與兩個包住完成的雙引號,數量仍是文字2或經明確轉型後的數值2。不要為了欄數看起來正確,把所有逗號與換行先刪掉,那會破壞操作記錄。
空白與空字串也要有約定。RFC的欄位空白不是自動可忽略字元,備註前後空格可能有意義。CSV本身也沒有通用的空值型別,空欄代表空文字、未知或無此資料,必須由欄位契約決定。
讀寫程式交給同一套格式規則
使用Python讀寫實體CSV檔案時,官方文件要求檔案以newline空字串方式開啟,讓csv模組處理換行;另明確指定encoding。否則平台文字換行轉換可能造成額外空行,或妨礙欄位內換行的正確處理。這是Python的檔案開啟設定,不是CSV欄位內容。
讀取時讓csv.reader持續解析整個文字串流,不要先用readlines分成獨立資料列再逐列拆逗號。解析器需要知道目前是否仍在引號內,才能判斷某次換行是欄位內容還是記錄結束。大量檔案可逐記錄處理,不必一次載入全部。
讀回後再驗證欄位個數、標題與型別。產品編號A001不應當數值,數量則在解析欄位後做明確整數驗證。CSV解析成功只代表語法可解,不表示日期、單位、數量範圍與業務資料都正確。
寫出前先在暫存位置完成整個檔案,確認筆數與格式後再按系統支援方式發布。接收端若邊讀仍在寫入的檔案,最後一筆可能只有半個引號欄位;這種問題不是新增更多分隔符號就能修好,需要完成狀態或交接協定。
設定合理的欄位大小與檔案容量限制,避免無止境的備註或未閉合引號讓處理流程耗盡資源。限制超過時保留原檔與明確錯誤位置,不能靜默截短到剛好能匯入;截短可能連後續記錄邊界一起破壞。
找出錯位發生在哪一層
失敗時先用同一CSV解析器讀回剛寫出的檔案。如果讀回正確而試算表錯位,查匯入分隔符號、引號及編碼設定;如果寫出後立刻讀回就錯,查手動串接、引號跳脫與寫檔是否完整。保留原始位元組,避免多次另存後失去第一現場。
未閉合引號不能靠猜測下一行必定是新產品來修復。先檢查是否檔案尚未寫完、傳輸截斷或來源漏寫引號;無法確認時隔離該檔並回報。自動把換行改空格可能讓匯入成功,卻把兩個產品的內容合成一筆。
接收端不支援多行欄位時,可另做顯示用單行欄,把換行轉成約定標記,同時保存原始備註。標記本身如何跳脫也要定義,例如原文字本來就包含同樣符號時如何區分;這是新交換契約,不能冒稱原文完全未變。
驗收資料包含正常文字、逗號、雙引號、單一換行、連續換行、空備註與中文。逐欄比較寫入前與讀回後的字串,不只比較檔案能否開啟。若交換契約會統一換行形式,將這項正規化列為明確允許的差異。
記錄匯入錯誤時同時保存邏輯記錄編號與解析器可提供的文字行位置,兩者在多行備註下不相同。修正來源檔後重新解析整筆記錄,不從備註中間某一行續讀。續傳若以任意位元組切檔,也須先確認切點沒有落在中文字或引號欄位內。
練習與常見問題
練習:建立兩筆三欄資料,第一筆備註含一個逗號、一個換行與一組雙引號,第二筆備註空白。寫出後讀回,應仍有兩筆,各三欄,第一筆備註字串完全一致,第二筆備註維持約定的空文字,不得變成上一筆的延續。
問:檔案行數等於資料筆數嗎?答:欄位允許換行時不相等,應由CSV解析器計算記錄。
問:把所有欄位加引號就不用處理內部引號嗎?答:仍要依CSV規則將內部雙引號成對寫出。
問:換行備註一定要刪掉才能匯入嗎?答:支援多行欄位的解析器可保留,受限設備則另訂明確格式。
問:讀回欄數正確就完成驗收嗎?答:還要逐欄核對內容、型別、編碼與資料交接完整性。
參考:RFC 4180:帶逗號、換行與雙引號欄位的包覆方式;屬資訊性文件。
參考:Python csv:reader、writer及newline設定。