一個號稱最高性能的CSV文件讀寫操作庫,支持AOT/NativeAOT。
01
項目簡介
Sep 是一個高性能的 .NET CSV 解析器,具備快速、現代、簡潔且高效的數據處理能力。
先進特性:采用 .NET 7+ 和 C# 11+ 的先進特性,例如 Span<T>、泛型數學接口(ISpanParsable<T>/ISpanFormattable)、ref struct、ArrayPool<T> 等,打造了一個現代且高效的實現方式。
簡潔API:提供了一個簡潔而富有表現力的 API,選項精簡,對輸入輸出的處理透明無隱藏。你看到什么就得到什么。例如,它默認不會自動處理引號的轉義/取消轉義。
極速性能:通過架構特定和跨平臺的 SIMD 矢量化解析技術,支持 64/128/256/512 位路徑(如 AVX2、AVX-512(.NET 8.0+)、NEON),實現極速處理。利用 csFastFloat 快速解析浮點數。高效地逐行讀取或寫入數據,并有詳盡的基準測試驗證其性能。
多線程加速:通過高效的并行 CSV 解析技術,實現超快速度,比 CsvHelper 快達 35 倍。
低內存占用:智能高效的內存管理策略,在預熱后實現零內存分配,包括輕松讀取或寫入值數組(如特征數據)而無需重復分配內存。
全面測試保障:擁有廣泛的代碼覆蓋率,專注于邊緣情況的測試,包括隨機模糊測試,確保數據處理的準確性和穩定性。
跨平臺兼容:支持 .NET 支持的所有平臺和架構,100% 托管,采用現代 C# 編寫,代碼優美。
可修剪且兼容 AOT/NativeAOT:無反射或動態代碼生成,確保完全可修剪且與提前編譯(Ahead-of-Time)兼容。簡單的控制臺測試程序,可執行文件體積小,僅幾 MB。
實用主義:遵循 RFC-4180 的核心原則,但在引用和行結束處理上采取實用主義方法。
02
使用方法
簡單示例代碼
using nietras.SeparatedValues;
// 指定CSV文件的路徑
string filePath = "file.csv";
// 使用Sep庫創建一個CSV讀取器,從文件中讀取數據
using var reader = Sep.Reader().FromFile(filePath);
// 遍歷CSV文件中的每一行
foreach (var readRow in reader)
{
// 假設我們知道CSV文件的列結構,可以直接通過列名訪問數據
string columnA = readRow["A"].ToString();
string columnB = readRow["B"].ToString();
int columnC = readRow["C"].Parse<int>();
double columnD = readRow["D"].Parse<double>();
// 處理每一行的數據
Console.WriteLine($"A: {columnA}, B: {columnB}, C: {columnC}, D: {columnD}");
}
格式化示例代碼
using nietras.SeparatedValues;
// 定義一個多行字符串,表示一個CSV格式的數據。
var text = """
A;B;C;D;E;F
Sep;??;1;1.2;0.1;0.5
CSV;?;2;2.2;0.2;1.5
""";
// 使用Sep庫創建一個CSV讀取器,自動從標題行推斷分隔符。
using var reader = Sep.Reader().FromText(text);
// 根據讀取器的規格創建一個寫入器,準備將數據寫入文本。
using var writer = reader.Spec.Writer().ToText();
// 獲取列"B"在標題中的索引位置。
var idx = reader.Header.IndexOf("B");
// 定義一個包含列名的數組。
var nms = new[] { "E", "F" };
// 遍歷讀取器中的每一行數據。
foreach (var readRow in reader)
{
// 將列"A"讀取為只讀的字符跨度。
var a = readRow["A"].Span;
// 將列"B"的值轉換為字符串。
var b = readRow[idx].ToString();
// 將列"C"的值解析為整數。
var c = readRow["C"].Parse<int>();
// 將列"D"的值解析為浮點數,使用csFastFloat庫進行快速解析。
var d = readRow["D"].Parse<float>();
// 將列"E"和"F"的值解析為雙精度浮點數的跨度。
var s = readRow[nms].Parse<double>();
// 遍歷解析后的數值,并將每個值乘以10。
foreach (ref var v in s) { v *= 10; }
// 開始寫入新一行數據,行數據在Dispose時寫入。
using var writeRow = writer.NewRow();
// 通過只讀的字符跨度設置列"A"的值。
writeRow["A"].Set(a);
// 通過字符串設置列"B"的值。
writeRow["B"].Set(b);
// 通過插值字符串處理器設置列"C"的值,不會產生新的內存分配。
writeRow["C"].Set($"{c * 2}");
// 格式化列"D"的值,將數值除以2。
writeRow["D"].Format(d / 2);
// 直接格式化多個列的值。
writeRow[nms].Format(s);
}
Console.WriteLine(writer.ToString());
03
項目地址
https://github.com/nietras/Sep
該文章在 2024/9/19 16:19:10 編輯過