Zaiets.CsvEngine
1.0.0
dotnet add package Zaiets.CsvEngine --version 1.0.0
NuGet\Install-Package Zaiets.CsvEngine -Version 1.0.0
<PackageReference Include="Zaiets.CsvEngine" Version="1.0.0" />
<PackageVersion Include="Zaiets.CsvEngine" Version="1.0.0" />
<PackageReference Include="Zaiets.CsvEngine" />
paket add Zaiets.CsvEngine --version 1.0.0
#r "nuget: Zaiets.CsvEngine, 1.0.0"
#:package Zaiets.CsvEngine@1.0.0
#addin nuget:?package=Zaiets.CsvEngine&version=1.0.0
#tool nuget:?package=Zaiets.CsvEngine&version=1.0.0
Zaiets.CsvEngine
High-performance CSV reader/writer for .NET — streaming, typed mapping, large files, custom delimiters.
Features
- RFC 4180 compliant — correct handling of quoted fields, embedded commas, and newlines inside quotes
- Streaming — reads and writes row-by-row; constant memory for arbitrarily large files
- Typed mapping — map CSV rows directly to your POCO classes via
CsvMapperor the[CsvColumn]attribute - Async-first — full
IAsyncEnumerable<CsvRow>support with cancellation - Custom delimiters — comma, tab, semicolon, pipe, or any character
- Fluent extensions —
string.ParseCsvAs<T>(),IEnumerable<T>.ToCsvString(), and more - Zero dependencies — pure .NET, no third-party packages
Installation
dotnet add package Zaiets.CsvEngine
Quick start
Read a file into a list of objects
using Zaiets.CsvEngine;
// products.csv:
// Id,Name,Price,InStock
// 1,Widget,9.99,true
// 2,Gadget,24.50,false
var products = Csv.ReadFile<Product>("products.csv");
foreach (var p in products)
Console.WriteLine($"{p.Name}: ${p.Price}");
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
public bool InStock { get; set; }
}
Write objects to a file
var products = new[]
{
new Product { Id = 1, Name = "Widget", Price = 9.99m, InStock = true },
new Product { Id = 2, Name = "Gadget", Price = 24.50m, InStock = false },
};
Csv.WriteFile("output.csv", products);
Parse a CSV string
string csv = """
Name,Score
Alice,95
Bob,82
""";
var records = csv.ParseCsvAs<StudentScore>();
// or without mapping:
var rows = csv.ParseCsvRows();
Console.WriteLine(rows[0]["Name"]); // Alice
Serialize to string
string csv = products.ToCsvString();
Attribute mapping
Use [CsvColumn] to control how properties map to columns:
public class Order
{
[CsvColumn("order_id")]
public int Id { get; set; }
[CsvColumn("customer_name")]
public string Customer { get; set; } = string.Empty;
[CsvColumn("order_date", Format = "yyyy-MM-dd")]
public DateOnly OrderDate { get; set; }
[CsvColumn("total_usd", DefaultValue = "0")]
public decimal Total { get; set; }
[CsvIgnore]
public string InternalNote { get; set; } = string.Empty; // never written/read
}
var orders = Csv.ReadFile<Order>("orders.csv");
You can also map by column index instead of name:
public class LogEntry
{
[CsvColumn(0)] public DateTime Timestamp { get; set; }
[CsvColumn(1)] public string Level { get; set; } = string.Empty;
[CsvColumn(2)] public string Message { get; set; } = string.Empty;
}
var opts = new CsvOptions { HasHeader = false };
var entries = Csv.ReadFile<LogEntry>("app.log", opts);
Custom delimiters
// Tab-separated
var opts = CsvOptions.Tab;
// Semicolon (European locale files)
var opts = CsvOptions.Semicolon;
// Any character
var opts = new CsvOptions { Delimiter = '|' };
Streaming large files
CsvReader and CsvMapper are fully lazy. Only one row is in memory at a time:
await using var reader = new CsvReader("huge.csv");
await foreach (var row in reader.ReadAllAsync(cancellationToken))
{
// process row.Get<int>("Id"), row["Name"], etc.
}
Or with type mapping:
await using var reader = new CsvReader("huge.csv");
await foreach (var item in CsvMapper.MapAsync<Product>(reader.ReadAllAsync()))
{
await db.InsertAsync(item);
}
Low-level row access
CsvRow supports both index and name-based access with optional type conversion:
using var reader = new CsvReader("data.csv");
foreach (var row in reader.ReadAll())
{
int id = row.Get<int>("Id");
string name = row["Name"];
decimal price = row.GetOrDefault<decimal>("Price", 0m);
bool inStock = row.Get<bool>(3); // by index
}
Low-level writing
await using var writer = new CsvWriter("report.csv");
await writer.WriteHeaderAsync("Date", "Revenue", "Region");
await writer.WriteValuesAsync(cancellationToken,
DateOnly.FromDateTime(DateTime.Today), 12_500.75m, "EMEA");
Stream and string extensions
// From a stream
await using var fs = File.OpenRead("data.csv");
var items = await fs.ReadCsvAsAsync<Product>();
// Write to a stream
await using var ms = new MemoryStream();
await products.WriteCsvAsync(ms);
// Save directly
await products.SaveCsvAsync("output.csv");
Options reference
| Property | Default | Description |
|---|---|---|
Delimiter |
, |
Field separator character |
Quote |
" |
Quote character for fields with special chars |
Escape |
" |
Escape character inside quoted fields (RFC 4180: doubled quote) |
HasHeader |
true |
Treat the first row as a header |
SkipEmptyLines |
true |
Skip blank lines |
TrimFields |
false |
Trim whitespace from each field |
AllowComments |
false |
Skip lines starting with CommentChar |
CommentChar |
# |
Comment line prefix |
Encoding |
UTF-8 | File encoding |
BufferSize |
65536 | Stream buffer size in bytes |
FormatProvider |
Invariant | Culture for number/date parsing |
NewLine |
System | Line ending written by CsvWriter |
License
MIT — see LICENSE.
Author
Vladyslav Zaiets — CTO & Software Architect
sarmkadan.com · github.com/Sarmkadan
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 127 | 5/3/2026 |