首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C# 實作 CSV 解析狀態機:單趟掃描、正確處理引號與跳脫

     編輯:程式設計綜合問答

為何需要狀態機?

CSV 格式看似簡單,實則包含引號包裹、內嵌逗號、雙引號跳脫 ("" 代表 ")、跨行欄位等邊界情況。正則表達式難以全面覆蓋且效能不可控,有限狀態機 (FSM) 以 O(n) 時間、O(1) 額外空間單趟掃描,是工業級解析器的標準實作。

狀態定義

  • Normal — 一般字元累積進當前欄位,遇逗號輸出欄位,遇雙引號進入 InQuote。
  • InQuote — 引號內字元原樣累積 (含逗號、換行),遇雙引號:若下一字元也是雙引號則寫入一個雙引號並跳過;否則結束引號區塊回 Normal。

完整可運行程式碼 (C#)

using System;
using System.Collections.Generic;
using System.Text;

public static class CsvParser
{
    public static List ParseLine(string line)
    {
        var result = new List();
        var current = new StringBuilder();
        bool inQuote = false;

        for (int i = 0; i < line.Length; i++)
        {
            char c = line[i];
            if (c == '"')
            {
                if (inQuote)
                {
                    // 可能是跳脫雙引號 或 結束引號
                    if (i + 1 < line.Length && line[i + 1] == '"')
                    {
                        current.Append('"'); // 寫入單個雙引號
                        i++; // 跳過下一個雙引號
                    }
                    else
                    {
                        inQuote = false; // 結束引號區塊
                    }
                }
                else
                {
                    inQuote = true; // 開始引號區塊
                }
            }
            else if (c == ',' && !inQuote)
            {
                // 欄位分隔
                result.Add(current.ToString());
                current.Clear();
            }
            else
            {
                current.Append(c);
            }
        }
        result.Add(current.ToString()); // 最後一欄
        return result;
    }
}

// 測試
var line = "1,2,3,\"4,5\",6,\"7\"\"8\"";
foreach (var f in CsvParser.ParseLine(line))
    Console.WriteLine($"[{f}]");
// 輸出: [1] [2] [3] [4,5] [6] [7"8]

擴展建議

  • 多行支援: 將輸入改為 TextReader 逐字讀取,狀態機邏輯不變,自然支援跨行欄位。
  • RFC 4180 合規: 處理 \r\n 行尾、空欄位、首尾空白保留選項。
  • 效能優化: 直接寫入 Span 或預分配陣列,避免 StringBuilder 擴容開銷。

總結

狀態機是解析上下文相關文法 (如 CSV、JSON、XML 子集) 的利器。掌握「狀態 + 輸入字元 → 動作 + 下一狀態」的建模思維,即可手寫高效、零依賴、全邊界覆蓋的解析器。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved