Note
In the following code examples - for easier readability - exception handling
has been omitted.
public static CsvReader<TResult> OpenRead<TResult>(
string filePath,
CsvMapping mapping,
Func<Object, TResult> conversion,
char delimiter = ',',
Encoding? textEncoding = null,
bool isHeaderPresent = true,
CsvOpts options = CsvOpts.Default
)
Public Shared Function OpenRead(Of TResult) (
filePath As String,
mapping As CsvMapping,
conversion As Func(Of Object, TResult),
Optional delimiter As Char = ","C,
Optional textEncoding As Encoding = Nothing,
Optional isHeaderPresent As Boolean = true,
Optional options As CsvOpts = CsvOpts.Default
) As CsvReader(Of TResult)
public:
generic<typename TResult>
static CsvReader<TResult>^ OpenRead(
String^ filePath,
CsvMapping^ mapping,
Func<Object^, TResult>^ conversion,
wchar_t delimiter = L',',
Encoding^ textEncoding = nullptr,
bool isHeaderPresent = true,
CsvOpts options = CsvOpts::Default
)
static member OpenRead :
filePath : string *
mapping : CsvMapping *
conversion : Func<Object, 'TResult> *
?delimiter : char *
?textEncoding : Encoding *
?isHeaderPresent : bool *
?options : CsvOpts
(* Defaults:
let _delimiter = defaultArg delimiter ','
let _textEncoding = defaultArg textEncoding null
let _isHeaderPresent = defaultArg isHeaderPresent true
let _options = defaultArg options CsvOpts.Default
*)
-> CsvReader<'TResult>
A function that converts the content of mapping to an instance of TResult.
The function is called for each row in the CSV file and gets the CsvMapping as argument, filled with the current CsvRecord instance. The CsvMapping is passed to the function as dynamic argument: Inside the function the registered DynamicProperty instances can be used like regular .NET properties, but without IntelliSense ("late binding").
The optimal parameters can be determined automatically with AnalyzeFile(String, Encoding, Header, Int32) - or use OpenReadAnalyzedTResult(String, CsvMapping, FuncObject, TResult, Encoding, Header, Int32).
When importing CSV data from Excel, the appropriate arguments can be determined with GetExcelArguments.
Object serialization with CSV:
using FolkerKinzel.CsvTools;
using FolkerKinzel.CsvTools.Mappings;
using System.Text;
// A namespace alias helps to avoid name conflicts
// with the converters from System.ComponentModel
using Conv = FolkerKinzel.CsvTools.Mappings.TypeConverters;
namespace Examples;
internal sealed record Pupil(string? Name, string? Subject, DayOfWeek? LessonDay, TimeOnly? LessonBegin);
internal static class ObjectSerializationExample
{
public static void CsvReadWritePupils(string filePath)
{
Pupil[] pupils = [
new("Susi", "Piano", DayOfWeek.Wednesday, new TimeOnly(14, 30)),
new("Carl Czerny", "Piano", DayOfWeek.Thursday, new TimeOnly(15, 15)),
new("Frederic Chopin", "Piano", null, null)
];
// A converter can be reused for more than one DynamicProperty:
Conv::TypeConverter<string?> stringConverter = Conv::StringConverter.CreateNullable();
// Initialize a CsvMapping that maps the data from the CSV-Columns and converts it to the right data type.
// Aliases with wildcards can be used to match the column-headers of the CSV file.
CsvMapping mapping = CsvMappingBuilder
.Create()
.AddProperty("Name", ["*name"], stringConverter)
.AddProperty("Subject", ["*subject", "*fach"], stringConverter)
.AddProperty("LessonDay", ["*day", "*tag"], new Conv::EnumConverter<DayOfWeek>().ToNullableConverter())
.AddProperty("LessonBegin", ["*begin?"], new Conv::TimeOnlyConverter().ToNullableConverter())
.Build();
// Create a CSV-File:
pupils.SaveCsv(filePath,
mapping,
static (pupil, mapping) =>
{
mapping.Name = pupil.Name;
mapping.Subject = pupil.Subject;
mapping.LessonDay = pupil.LessonDay;
mapping.LessonBegin = pupil.LessonBegin;
},
columnNames:
["Unterrichtstag", "Unterrichtsbeginn", "Vollständiger Name", "Unterrichtsfach"]);
Console.WriteLine(File.ReadAllText(filePath));
Console.WriteLine();
// Read the CSV file:
using CsvReader<Pupil> pupilsReader =
CsvConverter.OpenRead<Pupil>(filePath,
mapping,
static mapping => new Pupil(mapping.Name,
mapping.Subject,
mapping.LessonDay,
mapping.LessonBegin));
pupils = [.. pupilsReader];
// Write the results to the Console:
foreach (Pupil pupil in pupils)
{
Console.WriteLine(pupil);
}
}
}
/*
Console output:
Unterrichtstag,Unterrichtsbeginn,Vollständiger Name,Unterrichtsfach
3,14:30:00,Susi,Piano
4,15:15:00,Carl Czerny,Piano
,,Frederic Chopin,Piano
Pupil { Name = Susi, Subject = Piano, LessonDay = Wednesday, LessonBegin = 14:30 }
Pupil { Name = Carl Czerny, Subject = Piano, LessonDay = Thursday, LessonBegin = 15:15 }
Pupil { Name = Frederic Chopin, Subject = Piano, LessonDay = , LessonBegin = }
*/
ArgumentNullException | filePath, or mapping, or conversion is null. |
ArgumentException | filePath is not a valid file path. |
ArgumentOutOfRangeException | delimiter is either the double quotes " or a line break character ('\r' or '\n'). |
IOException | I/O error. |