FieldCount
public int FieldCount { get; }The number of fields written to the current record so far.
Class in CsvHelper
Writes CSV as UTF-8, RFC 4180 by default. Records end with CRLF (CsvWriterOptions.NewLine); fields containing the separator, a quote, CR or LF are enclosed in quotes with inner quotes doubled; every record has the same number of fields. The other modes of CsvWriterOptions.Mode escape fields with an escape character, write them as they are, or pad them to fixed widths. Records of CsvRecordAttribute types are written with WriteRecords<T>(IEnumerable<T>).
public sealed class CsvWriter : IDisposable, IAsyncDisposableCsvHelperCsvHelper.dllFields are written into an internal buffer; I/O only happens in EndRecord (when the buffer is mostly full), Flush and their async counterparts, so async callers never block.
A writer is not thread-safe: use it from one thread at a time, and finish each async call before starting the next. Nothing checks this; fields from two threads end up mixed in the output. To write records produced on several threads, write them from one thread, or lock around each whole record, from its first field to EndRecord. To format records on several threads, use ParallelWriteRecords<T>(IEnumerable<T>, int) or ParallelWrite. The options and the record writers do not change, so they can be shared between threads.
public int FieldCount { get; }The number of fields written to the current record so far.
public CsvWriterOptions Options { get; }The options this writer was created with.
public long RecordCount { get; }The number of complete records written so far (the header counts as a record).
public static CsvWriter Create(Stream stream, CsvWriterOptions? options = null, bool leaveOpen = false)Creates a writer that writes UTF-8 to a stream.
streamStreamoptionsCsvWriterOptions?null for CsvWriterOptions.Default.leaveOpenboolstream stays open when the writer is disposed.stream is null.options are not valid: a CsvWriterOptions.Separator that is not ASCII or is CR, LF or (in Rfc4180 mode) the quote, an CsvWriterOptions.Escape that cannot be used, or missing or non-positive CsvWriterOptions.FieldWidths in FixedWidth mode.public static CsvWriter Create(TextWriter textWriter, CsvWriterOptions? options = null, bool leaveOpen = false)Creates a writer that writes to a TextWriter.
textWriterTextWriteroptionsCsvWriterOptions?null for CsvWriterOptions.Default.leaveOpenbooltextWriter stays open when the writer is disposed.textWriter is null.options are not valid: a CsvWriterOptions.Separator that is not ASCII or is CR, LF or (in Rfc4180 mode) the quote, an CsvWriterOptions.Escape that cannot be used, or missing or non-positive CsvWriterOptions.FieldWidths in FixedWidth mode.public void Dispose()Ends an unfinished record (without checking its field count), writes the buffer to the destination, flushes it and disposes it, unless the writer was created with leaveOpen. Calling it again does nothing.
public ValueTask DisposeAsync()Ends an unfinished record (without checking its field count), asynchronously writes the buffer to the destination, flushes it and disposes it, unless the writer was created with leaveOpen. Calling it again does nothing.
public void EndRecord()Ends the current record with CRLF (CsvWriterOptions.NewLine). In Rfc4180 mode, a record whose only field is empty is written as "", so it does not read as an empty line. Writes the buffer to the destination when it is mostly full.
public ValueTask EndRecordAsync(CancellationToken cancellationToken = default)Ends the current record, flushing asynchronously when the buffer is mostly full. See EndRecord.
cancellationTokenCancellationTokencancellationToken was canceled.public void Flush()Writes buffered records to the destination and flushes it. The fields of an unfinished record are written too.
public ValueTask FlushAsync(CancellationToken cancellationToken = default)Asynchronously writes buffered records to the destination and flushes it. See Flush.
cancellationTokenCancellationTokencancellationToken was canceled.public void ParallelWrite<T>(IEnumerable<T> items, Action<CsvWriter, T> write, int maxDegreeOfParallelism = -1)Writes the records of each item with write, called on several threads, and writes them to the destination in input order: the output of a foreach loop that calls write with this writer.
TitemsIEnumerable<T>maxDegreeOfParallelismintitems or write is null.maxDegreeOfParallelism is 0 or less than -1.This thread enumerates items and writes to the destination, while workers call write for batches of items. The callback gets the worker's writer (or this writer, for the items written on this thread) and writes whole records of the item on it: fields and EndRecord, WriteRecord<T>(T) and the like, as many records as the item needs, or none. A record that it leaves unfinished throws InvalidOperationException. Do not flush or dispose that writer, or start a parallel write with it.
Calls run concurrently, so anything shared that the callback changes must be thread-safe, and so must the converters and CsvWriterOptions.ShouldQuote. No header is written: write it first, with WriteHeader(params ReadOnlySpan<string>) or WriteHeader<T>(). When records must have as many fields as the first (CsvWriterOptions.ValidateFieldCount) and none has been written, the items up to the first record are written on this thread before the workers start, and so are items that fit in one batch.
The callback's writer numbers records as if every item wrote one: at the start of an item, its RecordCount (the record index that CsvWriterOptions.ShouldQuote gets, and the record number in exception messages) is the RecordCount of this writer before the call plus the index of the item. After the call, RecordCount counts every record written. An exception, from the enumeration or from the callback, is thrown after the records of the items before it are written. Do not use this writer otherwise until the call returns.
public ValueTask ParallelWriteAsync<T>(IAsyncEnumerable<T> items, Action<CsvWriter, T> write, int maxDegreeOfParallelism = -1, CancellationToken cancellationToken = default)Writes the records of each item of an asynchronous sequence with write as ParallelWrite does, enumerating it and writing to the destination asynchronously.
TitemsIAsyncEnumerable<T>writeAction<CsvWriter, T>maxDegreeOfParallelismintcancellationTokenCancellationTokenitems, waiting for the workers and writing to the destination.items or write is null.maxDegreeOfParallelism is 0 or less than -1.cancellationToken was canceled.public ValueTask ParallelWriteAsync<T>(IEnumerable<T> items, Action<CsvWriter, T> write, int maxDegreeOfParallelism = -1, CancellationToken cancellationToken = default)Writes the records of each item with write as ParallelWrite does, writing to the destination asynchronously.
TitemsIEnumerable<T>writeAction<CsvWriter, T>maxDegreeOfParallelismintcancellationTokenCancellationTokenitems or write is null.maxDegreeOfParallelism is 0 or less than -1.cancellationToken was canceled.public void ParallelWriteRecords<T>(IEnumerable<T> records, int maxDegreeOfParallelism = -1)Writes records as WriteRecords<T>(IEnumerable<T>) does, formatting them on several threads: the output is the same, in the same order.
TrecordsIEnumerable<T>maxDegreeOfParallelismintrecords is null.records contains null.maxDegreeOfParallelism is 0 or less than -1.T is not a CsvRecordAttribute type or its records cannot be written, a record is not valid (see EndRecord), or this writer is the one a ParallelWrite callback got. An invalid record is discarded; the records before it are written, and none after it.This thread enumerates records and writes to the destination, while workers format batches of records, each with a writer of its own. The header, and the first record when it fixes the field count (CsvWriterOptions.ValidateFieldCount) or the columns of dynamic records, are written on this thread before the workers start, and so are records that fit in one batch.
The record writer, the converters and CsvWriterOptions.ShouldQuote are called on several threads at once, so they must be thread-safe; generated record writers are. What this writer has buffered is written to the destination before the first batch, and each batch as soon as the batches before it are, without flushing the destination. An exception, from the enumeration or from a record, is thrown after the records before it are written. Do not use this writer otherwise until the call returns.
public void ParallelWriteRecords<T>(IEnumerable<T> records, CsvRecordWriter<T> recordWriter, int maxDegreeOfParallelism = -1)Writes records with recordWriter, as WriteRecords<T>(IEnumerable<T>, CsvRecordWriter<T>) does, formatting them on several threads: the output is the same, in the same order. See ParallelWriteRecords<T>(IEnumerable<T>, int).
TrecordsIEnumerable<T>recordWriterCsvRecordWriter<T>maxDegreeOfParallelismintrecords or recordWriter is null.records contains null.maxDegreeOfParallelism is 0 or less than -1.The workers share recordWriter, so it must be thread-safe: one that keeps no state between calls of CsvRecordWriter<T>.Write is.
public ValueTask ParallelWriteRecordsAsync<T>(IAsyncEnumerable<T> records, int maxDegreeOfParallelism = -1, CancellationToken cancellationToken = default)Writes an asynchronous sequence of records as ParallelWriteRecords<T>(IEnumerable<T>, int) does, enumerating it and writing to the destination asynchronously.
TrecordsIAsyncEnumerable<T>maxDegreeOfParallelismintcancellationTokenCancellationTokenrecords, waiting for the workers and writing to the destination.records is null.records contains null.maxDegreeOfParallelism is 0 or less than -1.T is not a CsvRecordAttribute type or its records cannot be written, a record is not valid (see EndRecord), or this writer is the one a ParallelWrite callback got. An invalid record is discarded; the records before it are written, and none after it.cancellationToken was canceled.public ValueTask ParallelWriteRecordsAsync<T>(IEnumerable<T> records, int maxDegreeOfParallelism = -1, CancellationToken cancellationToken = default)Writes records as ParallelWriteRecords<T>(IEnumerable<T>, int) does, writing to the destination asynchronously.
TrecordsIEnumerable<T>maxDegreeOfParallelismintcancellationTokenCancellationTokenrecords is null.records contains null.maxDegreeOfParallelism is 0 or less than -1.T is not a CsvRecordAttribute type or its records cannot be written, a record is not valid (see EndRecord), or this writer is the one a ParallelWrite callback got. An invalid record is discarded; the records before it are written, and none after it.cancellationToken was canceled.public ValueTask ParallelWriteRecordsAsync<T>(IAsyncEnumerable<T> records, CsvRecordWriter<T> recordWriter, int maxDegreeOfParallelism = -1, CancellationToken cancellationToken = default)Writes an asynchronous sequence of records with recordWriter as ParallelWriteRecords<T>(IEnumerable<T>, CsvRecordWriter<T>, int) does, enumerating it and writing to the destination asynchronously.
TrecordsIAsyncEnumerable<T>recordWriterCsvRecordWriter<T>maxDegreeOfParallelismintcancellationTokenCancellationTokenrecords, waiting for the workers and writing to the destination.records or recordWriter is null.records contains null.maxDegreeOfParallelism is 0 or less than -1.cancellationToken was canceled.public ValueTask ParallelWriteRecordsAsync<T>(IEnumerable<T> records, CsvRecordWriter<T> recordWriter, int maxDegreeOfParallelism = -1, CancellationToken cancellationToken = default)Writes records with recordWriter as ParallelWriteRecords<T>(IEnumerable<T>, CsvRecordWriter<T>, int) does, writing to the destination asynchronously.
TrecordsIEnumerable<T>recordWriterCsvRecordWriter<T>maxDegreeOfParallelismintcancellationTokenCancellationTokenrecords or recordWriter is null.records contains null.maxDegreeOfParallelism is 0 or less than -1.cancellationToken was canceled.public static CsvWriter ToFile(string path, CsvWriterOptions? options = null, FileOptions fileOptions = FileOptions.None)Creates (or overwrites) a file, which other processes can read while it is written. The writer closes the file when it is disposed. See Create(Stream, CsvWriterOptions, bool).
pathstringoptionsCsvWriterOptions?null for CsvWriterOptions.Default.fileOptionsFileOptionspath is empty, or options are not valid (see Create(Stream, CsvWriterOptions, bool)).path is null.public void WriteComment(ReadOnlySpan<char> text)Writes a comment line: CsvWriterOptions.CommentPrefix, the text and the line ending. A text with line breaks becomes several comment lines, one per line. Comments are not records: they do not count in RecordCount or for the field count of records.
textReadOnlySpan<char>public void WriteComment(string? text)Writes a comment line: CsvWriterOptions.CommentPrefix, the text and the line ending. A text with line breaks becomes several comment lines, one per line. Comments are not records: they do not count in RecordCount or for the field count of records.
textstring?null writes the prefix alone.public void WriteField(ReadOnlySpan<byte> utf8)Writes a field from UTF-8 bytes.
utf8ReadOnlySpan<byte>public void WriteField(ReadOnlySpan<char> value)Writes a field from UTF-16 text.
valueReadOnlySpan<char>public void WriteField(bool value)Writes CsvWriterOptions.TrueValue or CsvWriterOptions.FalseValue: True or False by default.
valueboolpublic void WriteField(object? value)Writes any value: strings and UTF-8 formattable values directly, other IFormattable values with the configured format provider, anything else via object.ToString.
valueobject?null for CsvWriterOptions.NullValue (an empty field by default).public void WriteField(string? value)Writes a field from UTF-16 text. A null string is written as CsvWriterOptions.NullValue, an empty field by default.
valuestring?public void WriteField(DateOnly value, ReadOnlySpan<char> format = default)Writes a date as yyyy-MM-dd unless another format is given.
valueDateOnlyformatReadOnlySpan<char>format is not a valid date format.public void WriteField(DateTime value, ReadOnlySpan<char> format = default)Writes a date and time in ISO 8601 round-trip format ("O") unless another format is given.
valueDateTimeformatReadOnlySpan<char>format is not a valid date and time format.public void WriteField(DateTimeOffset value, ReadOnlySpan<char> format = default)Writes a date and time with offset in ISO 8601 round-trip format ("O") unless another format is given.
valueDateTimeOffsetformatReadOnlySpan<char>format is not a valid date and time format.public void WriteField(ReadOnlySpan<char> value, CsvQuoting quoting)Writes a field from UTF-16 text, quoted as quoting says instead of CsvWriterOptions.Quoting.
valueReadOnlySpan<char>quotingCsvQuotingquoting is not a CsvQuoting value.public void WriteField(string? value, CsvQuoting quoting)Writes a field from UTF-16 text, quoted as quoting says instead of CsvWriterOptions.Quoting.
valuestring?null is written as CsvWriterOptions.NullValue (an empty field, which CsvQuoting.Always quotes).quotingCsvQuotingquoting is not a CsvQuoting value.net10.0
public void WriteField<T>(T value, ReadOnlySpan<char> format = default) where T : IUtf8SpanFormattableWrites a value that formats itself as UTF-8 (numbers, Guid, ...), with the configured format provider. Without a format, double and float are written as the shortest text that round-trips, and dates and times (DateTime, DateTimeOffset, DateOnly, TimeOnly) in ISO 8601 round-trip format ("O").
TvalueTformatReadOnlySpan<char>T.format is not valid for T.netstandard2.1, netstandard2.0, net47
public void WriteField<T>(T value, ReadOnlySpan<char> format = default) where T : IFormattableWrites a formattable value (numbers, Guid, ...). Numbers in the invariant culture without a format are written straight to UTF-8; anything else through IFormattable.ToString. In the invariant culture without a format, double and float are written as the shortest text that round-trips, as on .NET Core 3.0 and later, and without a format, DateTime and DateTimeOffset in ISO 8601 round-trip format ("O").
TvalueTformatReadOnlySpan<char>T.format is not valid for T.net10.0
public void WriteField<T>(T? value, ReadOnlySpan<char> format = default) where T : struct, IUtf8SpanFormattableWrites a nullable value; null is written as CsvWriterOptions.NullValue, an empty field by default. See WriteField<T>(T, ReadOnlySpan<char>).
TvalueT?null.formatReadOnlySpan<char>T.format is not valid for T.netstandard2.1, netstandard2.0, net47
public void WriteField<T>(T? value, ReadOnlySpan<char> format = default) where T : struct, IFormattableWrites a nullable value; null is written as CsvWriterOptions.NullValue, an empty field by default. See WriteField<T>(T, ReadOnlySpan<char>).
TvalueT?null.formatReadOnlySpan<char>T.format is not valid for T.net10.0
public void WriteField<T>(T value, ReadOnlySpan<char> format, IFormatProvider? provider) where T : IUtf8SpanFormattableWrites a value that formats itself as UTF-8 with the given format provider instead of CsvWriterOptions.FormatProvider, such as a culture for one column. See WriteField<T>(T, ReadOnlySpan<char>).
TvalueTformatReadOnlySpan<char>T.providerIFormatProvider?null for the writer's.format is not valid for T.netstandard2.1, netstandard2.0, net47
public void WriteField<T>(T value, ReadOnlySpan<char> format, IFormatProvider? provider) where T : IFormattableWrites a formattable value with the given format provider instead of CsvWriterOptions.FormatProvider, such as a culture for one column. See WriteField<T>(T, ReadOnlySpan<char>).
TvalueTformatReadOnlySpan<char>T.providerIFormatProvider?null for the writer's.format is not valid for T.public void WriteHeader<T>()Writes the header of T, a CsvRecordAttribute type: a record with the names of its columns, which a reader maps back to its members.
TT is not a CsvRecordAttribute type or its records cannot be written, or the header is not a valid record (see EndRecord). The record is discarded.public void WriteHeader(params ReadOnlySpan<string> names)Writes a header record. It is an ordinary record: later records must have the same field count.
namesReadOnlySpan<string>names is empty, or the number of names differs from the first record. The record is discarded.public void WriteHeader(params string[] names)Writes a header record (for callers before C# 13, which cannot pass a params span).
namesstring[]names is empty, or the number of names differs from the first record. The record is discarded.public void WriteRecord(params ReadOnlySpan<string?> fields)Writes a complete record: the fields (see WriteField(string)) and then EndRecord. Fields already written to the current record come first.
fieldsReadOnlySpan<string?>null value is written as CsvWriterOptions.NullValue (an empty field by default).public void WriteRecord(params string?[] fields)Writes a complete record of strings from an array (also for callers before C# 13, which cannot pass a params span). See WriteRecord(params ReadOnlySpan<string>).
fieldsstring?[]null value is written as CsvWriterOptions.NullValue (an empty field by default).public void WriteRecord(string? field)Writes a complete record of one field (see WriteField(string)) and then EndRecord. Fields already written to the current record come first.
fieldstring?null is written as CsvWriterOptions.NullValue (an empty field by default).public void WriteRecord<T>(T record)Writes record, of a CsvRecordAttribute type, as a complete record: a field per column, formatted as its member's attributes say, then EndRecord. The record writer is created on the first call and reused while T stays the same.
TrecordTrecord is null.T is not a CsvRecordAttribute type or its records cannot be written, or the record is not valid (see EndRecord). The record is discarded.public ValueTask WriteRecordAsync(string?[] fields, CancellationToken cancellationToken = default)Writes a complete record and flushes asynchronously when the buffer is mostly full. See WriteRecord(params ReadOnlySpan<string>).
fieldsstring?[]null value is written as CsvWriterOptions.NullValue (an empty field by default).cancellationTokenCancellationTokencancellationToken was canceled.public ValueTask WriteRecordAsync<T>(T record, CancellationToken cancellationToken = default)Writes record as a complete record and flushes asynchronously when the buffer is mostly full. See WriteRecord<T>(T).
TrecordTcancellationTokenCancellationTokenrecord is null.T is not a CsvRecordAttribute type or its records cannot be written, or the record is not valid (see EndRecord). The record is discarded.cancellationToken was canceled.public void WriteRecords<T>(IEnumerable<T> records)Writes records, of a CsvRecordAttribute type: first the header of T when nothing has been written yet (RecordCount is 0) and CsvWriterOptions.HasHeader is on, then each record.
TrecordsIEnumerable<T>records is null.records contains null.T is not a CsvRecordAttribute type or its records cannot be written, or a record is not valid (see EndRecord). That record is discarded; the records before it are written.public void WriteRecords<T>(IEnumerable<T> records, CsvRecordWriter<T> recordWriter)Writes records with recordWriter, as WriteRecords<T>(IEnumerable<T>) writes them with the generated one: the header first when nothing has been written yet and CsvWriterOptions.HasHeader is set, then a record per element. For a record writer of your own, such as one for a type that has no generated writer, without registering it for the type (CsvRecordWriter.Register).
TrecordsIEnumerable<T>recordWriterCsvRecordWriter<T>records or recordWriter is null.records contains null.public ValueTask WriteRecordsAsync<T>(IAsyncEnumerable<T> records, CancellationToken cancellationToken = default)Writes an asynchronous sequence of records as WriteRecords<T>(IEnumerable<T>) does, flushing asynchronously whenever the buffer is mostly full, so it never blocks on I/O.
TrecordsIAsyncEnumerable<T>cancellationTokenCancellationTokenrecords and writing to the destination.records is null.records contains null.T is not a CsvRecordAttribute type or its records cannot be written, or a record is not valid (see EndRecord). That record is discarded; the records before it are written.cancellationToken was canceled.public ValueTask WriteRecordsAsync<T>(IEnumerable<T> records, CancellationToken cancellationToken = default)Writes records as WriteRecords<T>(IEnumerable<T>) does, flushing asynchronously whenever the buffer is mostly full, so it never blocks on I/O.
TrecordsIEnumerable<T>cancellationTokenCancellationTokenrecords is null.records contains null.T is not a CsvRecordAttribute type or its records cannot be written, or a record is not valid (see EndRecord). That record is discarded; the records before it are written.cancellationToken was canceled.public ValueTask WriteRecordsAsync<T>(IAsyncEnumerable<T> records, CsvRecordWriter<T> recordWriter, CancellationToken cancellationToken = default)Writes an asynchronous sequence of records with recordWriter, as WriteRecords<T>(IEnumerable<T>, CsvRecordWriter<T>) does, flushing asynchronously whenever the buffer is mostly full, so it never blocks on I/O.
TrecordsIAsyncEnumerable<T>recordWriterCsvRecordWriter<T>cancellationTokenCancellationTokenrecords and writing to the destination.records or recordWriter is null.records contains null.cancellationToken was canceled.public ValueTask WriteRecordsAsync<T>(IEnumerable<T> records, CsvRecordWriter<T> recordWriter, CancellationToken cancellationToken = default)Writes records with recordWriter, as WriteRecords<T>(IEnumerable<T>, CsvRecordWriter<T>) does, flushing asynchronously whenever the buffer is mostly full, so it never blocks on I/O.
TrecordsIEnumerable<T>recordWriterCsvRecordWriter<T>cancellationTokenCancellationTokenrecords or recordWriter is null.records contains null.cancellationToken was canceled.