CSV(逗號分隔值)是最通用的資料交換格式。C# 歷史上有多種讀取方式,從手動解析到資料庫驅動、再到現代高效能庫。本文整理四大經典方法,附完整代碼與優缺點對比,助你根據場景選型。
var input = Request.Files[0]; // Web 上傳情境
if (input != null && input.ContentLength > 0)
{
using (var reader = new StreamReader(input.InputStream))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var columns = line.Split(',');
if (columns.Length >= 2 && !string.IsNullOrEmpty(columns[0]) && !string.IsNullOrEmpty(columns[1]))
{
// 處理 columns[0], columns[1]
// 此處原始碼有邏輯缺陷:DataSet 在迴圈內重複建立
}
}
}
}
優點:零依賴、完全控制解析邏輯。
缺點:需自行處理引號、逸出字元、換行符等 CSV 複雜規則;效能較低;易寫出 Bug(如原始碼中 DataSet 重複建立)。
SELECT * INTO theImportTable
FROM OPENROWSET('MSDASQL',
'Driver={Microsoft Text Driver (*.txt; *.csv)};DEFAULTDIR=D:;Extensions=CSV;',
'SELECT * FROM CSVFile.csv')
優點:T-SQL 一行搞定匯入,適合 SQL Server 端批次作業。
缺點:需安裝/啟用 32/64 位元 Text Driver、設定連結伺服器、權限複雜、除錯困難、跨平台不支援。
var connStr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\;Extended Properties='Text;HDR=YES;FMT=Delimited'";
using (var conn = new OleDbConnection(connStr))
using (var cmd = new OleDbCommand("SELECT * FROM CSVFile.csv", conn))
using (var adapter = new OleDbDataAdapter(cmd))
{
var dt = new DataTable();
adapter.Fill(dt); // 直接填充 DataTable
}
優點:自動處理標題列、型別推斷、引號逸出;回傳 DataTable 方便繫結。
缺點:依賴 ACE/OLEDB Provider(需安裝)、32/64 位元匹配問題、大檔案記憶體壓力大、效能一般。
var dt = new DataTable("myTable");
using (var sr = new StreamReader(path))
{
string headerLine = sr.ReadLine();
if (headerLine == null) return dt;
var headers = headerLine.Split('|'); // 自訂分隔符
foreach (var h in headers) dt.Columns.Add(h);
while (!sr.EndOfStream)
{
var line = sr.ReadLine();
var cols = line.Split('|');
var row = dt.NewRow();
for (int i = 0; i < cols.Length && i < dt.Columns.Count; i++)
row[i] = cols[i];
dt.Rows.Add(row);
}
}
優點:無外部依賴、支援自訂分隔符、串流處理不載入全檔、彈性控制欄位型別。
缺點:仍需自行處理 CSV 複雜規則(引號內逗號、跨行欄位等)。
生產環境強烈建議使用成熟庫:
// CsvHelper (NuGet)
using (var reader = new StreamReader(path))
using (var csv = new CsvHelper.CsvReader(reader, CultureInfo.InvariantCulture))
{
var records = csv.GetRecords<MyDto>().ToList(); // 強型別直接對應
}
// Sylvan.Data.Csv (高效能 DataReader)
using (var reader = Sylvan.Data.Csv.CsvDataReader.Create(path))
{
var dt = new DataTable();
dt.Load(reader); // 秒級載入百萬列
}
| 場景 | 推薦方法 | 關鍵理由 |
|---|---|---|
| 簡單小檔、無依賴要求 | 方法四 (手動 DataTable) | 可控、串流、無套件 |
| SQL Server 端 ETL | 方法二 (OPENROWSET) | 純 SQL、伺服器端完成 |
| 桌面應用匯入 Excel/CSV | 方法三 | 自動型別、DataTable 繫結 |
| 高效能/生產級/強型別 | CsvHelper / Sylvan | RFC 4180 相容、效能極致、維護性佳 |
| Web 上傳即時解析 | CsvHelper (Stream) | 非同步串流、記憶體恆定 |
CSV 解析看似簡單,實則暗藏 RFC 4180 規範複雜度(引號、逸出、換行)。手動 Split 仅适合教學或極簡場景,生產系統請直接採用 CsvHelper 或 Sylvan.Data.Csv,以標準庫換取正確性、效能與維護性。若受限無法引入套件,方法四(串流 + DataTable)為最佳手動替代方案。