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