-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathCsvFile.cs
More file actions
532 lines (510 loc) · 29.1 KB
/
CsvFile.cs
File metadata and controls
532 lines (510 loc) · 29.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
using BytecodeApi.Extensions;
using Microsoft.VisualBasic.FileIO;
using System.Reflection;
using System.Text;
namespace BytecodeApi.CsvParser;
/// <summary>
/// Represents a database read from a CSV files with lines separated by a delimiter.
/// </summary>
public class CsvFile
{
/// <summary>
/// Gets or sets the delimiter detector to be used when reading a CSV file and the delimiter parameter is <see langword="null" />.
/// <para>This property is global for the <see cref="CsvFile" /> class.</para>
/// <para>Default values are:</para>
/// <para><see cref="CsvDelimiterDetector.DelimitersToTest" /> = ",", ";", "\t", "|"</para>
/// <para><see cref="CsvDelimiterDetector.MinRowsToTest" /> = 2</para>
/// <para><see cref="CsvDelimiterDetector.MaxRowsToTest" /> = 10</para>
/// </summary>
public static CsvDelimiterDetector DelimiterDetector { get; set; }
/// <summary>
/// Gets or sets a <see cref="string" />[] that contains the headers of this CSV file or <see langword="null" />, if the hasHeaderRow parameter was set to <see langword="false" />.
/// </summary>
public string[]? Headers { get; set; }
/// <summary>
/// Gets or sets the delimiter for this CSV file. The initial value is set to the specified or detected delimiter when loading the CSV file, or <see langword="null" />, if the constructor was used to create an empty <see cref="CsvFile" />. This property is used by the <see cref="Save(Stream, bool, Encoding, bool)" /> method.
/// </summary>
public string? Delimiter { get; set; }
/// <summary>
/// Gets a collection of <see cref="CsvRow" /> objects that represents the content of this CSV file.
/// </summary>
public CsvRowCollection Rows { get; }
/// <summary>
/// Gets a <see cref="bool" /> value indicating whether this CSV file contains rows that could not be parsed. This property does not change once the file is loaded.
/// </summary>
public bool HasErrors { get; private set; }
/// <summary>
/// Gets a <see cref="bool" /> value indicating whether all rows in this CSV file have the same amount of columns, excluding the <see cref="Headers" /> property and error lines. If zero rows or only error rows were loaded, this property returns <see langword="true" />. This property does not change once the file is loaded.
/// </summary>
public bool IsColumnCountConsistent { get; private set; }
static CsvFile()
{
DelimiterDetector = CsvDelimiterDetector.CreateDefault();
}
/// <summary>
/// Initializes a new instance of the <see cref="CsvFile" /> class.
/// </summary>
public CsvFile()
{
Rows = [];
IsColumnCountConsistent = true;
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified file.
/// </summary>
/// <param name="path">A <see cref="string" /> representing the path to a CSV file.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromFile(string path)
{
return FromFile(path, false);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified file.
/// </summary>
/// <param name="path">A <see cref="string" /> representing the path to a CSV file.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromFile(string path, bool hasHeaderRow)
{
return FromFile(path, hasHeaderRow, null);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified file.
/// </summary>
/// <param name="path">A <see cref="string" /> representing the path to a CSV file.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <param name="delimiter">A <see cref="string" /> specifying the delimiter to be used during CSV parsing. If <see langword="null" /> is provided, the delimiter is automatically detected. If automatic detection fails, an exception is thrown.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromFile(string path, bool hasHeaderRow, string? delimiter)
{
return FromFile(path, hasHeaderRow, delimiter, false);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified file.
/// </summary>
/// <param name="path">A <see cref="string" /> representing the path to a CSV file.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <param name="delimiter">A <see cref="string" /> specifying the delimiter to be used during CSV parsing. If <see langword="null" /> is provided, the delimiter is automatically detected. If automatic detection fails, an exception is thrown.</param>
/// <param name="ignoreEmptyLines"><see langword="true" /> to ignore empty lines and lines where all columns are empty.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromFile(string path, bool hasHeaderRow, string? delimiter, bool ignoreEmptyLines)
{
return FromFile(path, hasHeaderRow, delimiter, ignoreEmptyLines, null);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified file.
/// </summary>
/// <param name="path">A <see cref="string" /> representing the path to a CSV file.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <param name="delimiter">A <see cref="string" /> specifying the delimiter to be used during CSV parsing. If <see langword="null" /> is provided, the delimiter is automatically detected. If automatic detection fails, an exception is thrown.</param>
/// <param name="ignoreEmptyLines"><see langword="true" /> to ignore empty lines and lines where all columns are empty.</param>
/// <param name="encoding">The encoding to use if encoding is not determined from the file. Specify <see langword="null" /> to detect encoding automatically or provide a value to explicitly parse with a specific <see cref="Encoding" />.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromFile(string path, bool hasHeaderRow, string? delimiter, bool ignoreEmptyLines, Encoding? encoding)
{
Check.ArgumentNull(path);
Check.FileNotFound(path);
Check.ArgumentEx.StringNotEmpty(delimiter);
using FileStream file = File.OpenRead(path);
return FromStream(file, hasHeaderRow, delimiter, ignoreEmptyLines, encoding);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="byte" />[] that represents a CSV file.
/// </summary>
/// <param name="file">The <see cref="byte" />[] that represents a CSV file to read from.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromBinary(byte[] file)
{
return FromBinary(file, false);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="byte" />[] that represents a CSV file.
/// </summary>
/// <param name="file">The <see cref="byte" />[] that represents a CSV file to read from.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromBinary(byte[] file, bool hasHeaderRow)
{
return FromBinary(file, hasHeaderRow, null);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="byte" />[] that represents a CSV file.
/// </summary>
/// <param name="file">The <see cref="byte" />[] that represents a CSV file to read from.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <param name="delimiter">A <see cref="string" /> specifying the delimiter to be used during CSV parsing. If <see langword="null" /> is provided, the delimiter is automatically detected. If automatic detection fails, an exception is thrown.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromBinary(byte[] file, bool hasHeaderRow, string? delimiter)
{
return FromBinary(file, hasHeaderRow, delimiter, false);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="byte" />[] that represents a CSV file.
/// </summary>
/// <param name="file">The <see cref="byte" />[] that represents a CSV file to read from.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <param name="delimiter">A <see cref="string" /> specifying the delimiter to be used during CSV parsing. If <see langword="null" /> is provided, the delimiter is automatically detected. If automatic detection fails, an exception is thrown.</param>
/// <param name="ignoreEmptyLines"><see langword="true" /> to ignore empty lines and lines where all columns are empty.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromBinary(byte[] file, bool hasHeaderRow, string? delimiter, bool ignoreEmptyLines)
{
return FromBinary(file, hasHeaderRow, delimiter, ignoreEmptyLines, null);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="byte" />[] that represents a CSV file.
/// </summary>
/// <param name="file">The <see cref="byte" />[] that represents a CSV file to read from.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <param name="delimiter">A <see cref="string" /> specifying the delimiter to be used during CSV parsing. If <see langword="null" /> is provided, the delimiter is automatically detected. If automatic detection fails, an exception is thrown.</param>
/// <param name="ignoreEmptyLines"><see langword="true" /> to ignore empty lines and lines where all columns are empty.</param>
/// <param name="encoding">The encoding to use if encoding is not determined from the file. Specify <see langword="null" /> to detect encoding automatically or provide a value to explicitly parse with a specific <see cref="Encoding" />.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromBinary(byte[] file, bool hasHeaderRow, string? delimiter, bool ignoreEmptyLines, Encoding? encoding)
{
Check.ArgumentNull(file);
Check.ArgumentEx.StringNotEmpty(delimiter);
using MemoryStream memoryStream = new(file);
return FromStream(memoryStream, hasHeaderRow, delimiter, ignoreEmptyLines, encoding);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="string" /> that represents the contents of a CSV file.
/// </summary>
/// <param name="csv">The <see cref="string" /> that represents the contents of a CSV file to read from.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromString(string csv)
{
return FromString(csv, false);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="string" /> that represents the contents of a CSV file.
/// </summary>
/// <param name="csv">The <see cref="string" /> that represents the contents of a CSV file to read from.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromString(string csv, bool hasHeaderRow)
{
return FromString(csv, hasHeaderRow, null);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="string" /> that represents the contents of a CSV file.
/// </summary>
/// <param name="csv">The <see cref="string" /> that represents the contents of a CSV file to read from.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <param name="delimiter">A <see cref="string" /> specifying the delimiter to be used during CSV parsing. If <see langword="null" /> is provided, the delimiter is automatically detected. If automatic detection fails, an exception is thrown.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromString(string csv, bool hasHeaderRow, string? delimiter)
{
return FromString(csv, hasHeaderRow, delimiter, false);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="string" /> that represents the contents of a CSV file.
/// </summary>
/// <param name="csv">The <see cref="string" /> that represents the contents of a CSV file to read from.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <param name="delimiter">A <see cref="string" /> specifying the delimiter to be used during CSV parsing. If <see langword="null" /> is provided, the delimiter is automatically detected. If automatic detection fails, an exception is thrown.</param>
/// <param name="ignoreEmptyLines"><see langword="true" /> to ignore empty lines and lines where all columns are empty.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromString(string csv, bool hasHeaderRow, string? delimiter, bool ignoreEmptyLines)
{
return FromBinary(csv.ToUTF8Bytes(), hasHeaderRow, delimiter, ignoreEmptyLines, Encoding.UTF8);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="Stream" />.
/// </summary>
/// <param name="stream">The <see cref="Stream" /> from which to read the CSV file from.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromStream(Stream stream)
{
return FromStream(stream, false);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="Stream" />.
/// </summary>
/// <param name="stream">The <see cref="Stream" /> from which to read the CSV file from.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromStream(Stream stream, bool hasHeaderRow)
{
return FromStream(stream, hasHeaderRow, null);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="Stream" />.
/// </summary>
/// <param name="stream">The <see cref="Stream" /> from which to read the CSV file from.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <param name="delimiter">A <see cref="string" /> specifying the delimiter to be used during CSV parsing. If <see langword="null" /> is provided, the delimiter is automatically detected. If automatic detection fails, an exception is thrown.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromStream(Stream stream, bool hasHeaderRow, string? delimiter)
{
return FromStream(stream, hasHeaderRow, delimiter, false);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="Stream" />.
/// </summary>
/// <param name="stream">The <see cref="Stream" /> from which to read the CSV file from.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <param name="delimiter">A <see cref="string" /> specifying the delimiter to be used during CSV parsing. If <see langword="null" /> is provided, the delimiter is automatically detected. If automatic detection fails, an exception is thrown.</param>
/// <param name="ignoreEmptyLines"><see langword="true" /> to ignore empty lines and lines where all columns are empty.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromStream(Stream stream, bool hasHeaderRow, string? delimiter, bool ignoreEmptyLines)
{
return FromStream(stream, hasHeaderRow, delimiter, ignoreEmptyLines, null);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="Stream" />.
/// </summary>
/// <param name="stream">The <see cref="Stream" /> from which to read the CSV file from.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <param name="delimiter">A <see cref="string" /> specifying the delimiter to be used during CSV parsing. If <see langword="null" /> is provided, the delimiter is automatically detected. If automatic detection fails, an exception is thrown.</param>
/// <param name="ignoreEmptyLines"><see langword="true" /> to ignore empty lines and lines where all columns are empty.</param>
/// <param name="encoding">The encoding to use if encoding is not determined from the file. Specify <see langword="null" /> to detect encoding automatically or provide a value to explicitly parse with a specific <see cref="Encoding" />.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromStream(Stream stream, bool hasHeaderRow, string? delimiter, bool ignoreEmptyLines, Encoding? encoding)
{
return FromStream(stream, hasHeaderRow, delimiter, ignoreEmptyLines, encoding, false);
}
/// <summary>
/// Creates a <see cref="CsvFile" /> object from the specified <see cref="Stream" />.
/// </summary>
/// <param name="stream">The <see cref="Stream" /> from which to read the CSV file from.</param>
/// <param name="hasHeaderRow"><see langword="true" /> to treat the first row as a header row and load its contents into the <see cref="Headers" /> property.</param>
/// <param name="delimiter">A <see cref="string" /> specifying the delimiter to be used during CSV parsing. If <see langword="null" /> is provided, the delimiter is automatically detected. If automatic detection fails, an exception is thrown.</param>
/// <param name="ignoreEmptyLines"><see langword="true" /> to ignore empty lines and lines where all columns are empty.</param>
/// <param name="encoding">The encoding to use if encoding is not determined from the file. Specify <see langword="null" /> to detect encoding automatically or provide a value to explicitly parse with a specific <see cref="Encoding" />.</param>
/// <param name="leaveOpen">A <see cref="bool" /> value indicating whether to leave <paramref name="stream" /> open.</param>
/// <returns>
/// The <see cref="CsvFile" /> this method creates.
/// </returns>
public static CsvFile FromStream(Stream stream, bool hasHeaderRow, string? delimiter, bool ignoreEmptyLines, Encoding? encoding, bool leaveOpen)
{
Check.ArgumentNull(stream);
Check.ArgumentEx.StringNotEmpty(delimiter);
CsvHelper.AutoDetectDelimiter(DelimiterDetector, stream, encoding, ref delimiter);
using TextFieldParser parser = CsvHelper.CreateTextFieldParser(stream, delimiter, encoding, leaveOpen, out FieldInfo lineNumberField);
CsvFile csv = new() { Delimiter = delimiter };
if (hasHeaderRow)
{
try
{
csv.Headers = parser.ReadFields();
}
catch (MalformedLineException)
{
csv.HasErrors = true;
}
}
int columnCount = -1;
foreach (CsvRow row in CsvHelper.EnumerateTextFieldParser(parser, ignoreEmptyLines))
{
row.LineNumber = lineNumberField.GetValue(parser) is long lineNumber ? lineNumber - 1 : throw Throw.InvalidOperation("Error retrieving line number.");
if (row.ErrorLine != null)
{
csv.HasErrors = true;
}
if (row.ErrorLine == null && csv.IsColumnCountConsistent)
{
if (columnCount == -1)
{
columnCount = row.Count;
}
else if (columnCount != row.Count)
{
csv.IsColumnCountConsistent = false;
}
}
csv.Rows.Add(row);
}
return csv;
}
/// <summary>
/// Checks whether the column count of all rows is equal to <paramref name="columnCount" />, excluding the <see cref="Headers" /> property and error rows.
/// </summary>
/// <param name="columnCount">A <see cref="int" /> value specifying the expected column count for all rows.</param>
/// <returns>
/// <see langword="true" />, if the column count of all rows is equal to <paramref name="columnCount" />, or it no rows were imported;
/// otherwise, <see langword="false" />.
/// </returns>
public bool CheckColumnCount(int columnCount)
{
if (IsColumnCountConsistent)
{
return Rows.Count == 0 || Rows.First().Count == columnCount;
}
else
{
return Rows.All(row => row.Count == columnCount);
}
}
/// <summary>
/// Tries to find the column index of a specified case sensitive column header name. Returns -1, if the column header was not found.
/// </summary>
/// <param name="header">A <see cref="string" /> specifying the case sensitive name of the column header to search for.</param>
/// <returns>
/// The zero-based index of the column header, or -1, if the column header was not found.
/// </returns>
public int GetColumnIndex(string header)
{
return GetColumnIndex(header, false);
}
/// <summary>
/// Tries to find the column index of a specified case header name. Returns -1, if the column header was not found.
/// </summary>
/// <param name="header">A <see cref="string" /> specifying the case sensitive name of the column header to search for.</param>
/// <param name="ignoreCase"><see langword="true" /> to ignore character casing during column name comparison.</param>
/// <returns>
/// The zero-based index of the column header, or -1, if the column header was not found.
/// </returns>
public int GetColumnIndex(string header, bool ignoreCase)
{
return Headers?.IndexOf(h => h.Equals(header, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) ?? -1;
}
/// <summary>
/// Writes the contents of this CSV to a file. If <see cref="Headers" /> is not <see langword="null" />, the header row is included. The <see cref="Delimiter" /> property specifies the delimiter to use when writing.
/// </summary>
/// <param name="path">A <see cref="string" /> specifying the path to a file to which this CSV file is written to.</param>
public void Save(string path)
{
Save(path, false);
}
/// <summary>
/// Writes the contents of this CSV to a file. If <see cref="Headers" /> is not <see langword="null" />, the header row is included. The <see cref="Delimiter" /> property specifies the delimiter to use when writing.
/// </summary>
/// <param name="path">A <see cref="string" /> specifying the path to a file to which this CSV file is written to.</param>
/// <param name="alwaysQuote"><see langword="true" /> to wrap all cells with quotes; <see langword="false" /> to only use quotes when needed.</param>
public void Save(string path, bool alwaysQuote)
{
Save(path, alwaysQuote, null);
}
/// <summary>
/// Writes the contents of this CSV to a file. If <see cref="Headers" /> is not <see langword="null" />, the header row is included. The <see cref="Delimiter" /> property specifies the delimiter to use when writing.
/// </summary>
/// <param name="path">A <see cref="string" /> specifying the path to a file to which this CSV file is written to.</param>
/// <param name="alwaysQuote"><see langword="true" /> to wrap all cells with quotes; <see langword="false" /> to only use quotes when needed.</param>
/// <param name="encoding">The encoding to use to write to the file.</param>
public void Save(string path, bool alwaysQuote, Encoding? encoding)
{
Check.ArgumentNull(path);
Check.ArgumentNull(Delimiter);
Check.ArgumentEx.StringNotEmpty(Delimiter);
using FileStream stream = File.Create(path);
Save(stream, alwaysQuote, encoding, false);
}
/// <summary>
/// Writes the contents of this CSV to a <see cref="Stream" />. If <see cref="Headers" /> is not <see langword="null" />, the header row is included. The <see cref="Delimiter" /> property specifies the delimiter to use when writing.
/// </summary>
/// <param name="stream">The <see cref="Stream" /> to which this CSV is written to.</param>
public void Save(Stream stream)
{
Save(stream, false);
}
/// <summary>
/// Writes the contents of this CSV to a <see cref="Stream" />. If <see cref="Headers" /> is not <see langword="null" />, the header row is included. The <see cref="Delimiter" /> property specifies the delimiter to use when writing.
/// </summary>
/// <param name="stream">The <see cref="Stream" /> to which this CSV is written to.</param>
/// <param name="alwaysQuote"><see langword="true" /> to wrap all cells with quotes; <see langword="false" /> to only use quotes when needed.</param>
public void Save(Stream stream, bool alwaysQuote)
{
Save(stream, alwaysQuote, null);
}
/// <summary>
/// Writes the contents of this CSV to a <see cref="Stream" />. If <see cref="Headers" /> is not <see langword="null" />, the header row is included. The <see cref="Delimiter" /> property specifies the delimiter to use when writing.
/// </summary>
/// <param name="stream">The <see cref="Stream" /> to which this CSV is written to.</param>
/// <param name="alwaysQuote"><see langword="true" /> to wrap all cells with quotes; <see langword="false" /> to only use quotes when needed.</param>
/// <param name="encoding">The encoding to use to write to the file.</param>
public void Save(Stream stream, bool alwaysQuote, Encoding? encoding)
{
Save(stream, alwaysQuote, encoding, false);
}
/// <summary>
/// Writes the contents of this CSV to a <see cref="Stream" />. If <see cref="Headers" /> is not <see langword="null" />, the header row is included. The <see cref="Delimiter" /> property specifies the delimiter to use when writing.
/// </summary>
/// <param name="stream">The <see cref="Stream" /> to which this CSV is written to.</param>
/// <param name="alwaysQuote"><see langword="true" /> to wrap all cells with quotes; <see langword="false" /> to only use quotes when needed.</param>
/// <param name="encoding">The encoding to use to write to the file.</param>
/// <param name="leaveOpen">A <see cref="bool" /> value indicating whether to leave <paramref name="stream" /> open.</param>
public void Save(Stream stream, bool alwaysQuote, Encoding? encoding, bool leaveOpen)
{
Check.ArgumentNull(stream);
Check.ArgumentNull(Delimiter);
Check.ArgumentEx.StringNotEmpty(Delimiter);
if (Headers?.Any() == true)
{
CsvIterator.ToStream(stream, [new CsvRow(Headers)], Delimiter, alwaysQuote, encoding, true);
}
CsvIterator.ToStream(stream, Rows, Delimiter, alwaysQuote, encoding, leaveOpen);
}
/// <summary>
/// Converts this <see cref="CsvFile" /> to its <see cref="byte" />[] representation.
/// </summary>
/// <returns>
/// A new <see cref="byte" />[] representing this <see cref="CsvFile" />.
/// </returns>
public byte[] Save()
{
return Save(false);
}
/// <summary>
/// Converts this <see cref="CsvFile" /> to its <see cref="byte" />[] representation.
/// </summary>
/// <param name="alwaysQuote"><see langword="true" /> to wrap all cells with quotes; <see langword="false" /> to only use quotes when needed.</param>
/// <returns>
/// A new <see cref="byte" />[] representing this <see cref="CsvFile" />.
/// </returns>
public byte[] Save(bool alwaysQuote)
{
return Save(alwaysQuote, null);
}
/// <summary>
/// Converts this <see cref="CsvFile" /> to its <see cref="byte" />[] representation.
/// </summary>
/// <param name="alwaysQuote"><see langword="true" /> to wrap all cells with quotes; <see langword="false" /> to only use quotes when needed.</param>
/// <param name="encoding">The encoding to use to write to the file.</param>
/// <returns>
/// A new <see cref="byte" />[] representing this <see cref="CsvFile" />.
/// </returns>
public byte[] Save(bool alwaysQuote, Encoding? encoding)
{
using MemoryStream memoryStream = new();
Save(memoryStream, alwaysQuote, encoding, false);
return memoryStream.ToArray();
}
}