-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathCsvHelper.cs
More file actions
55 lines (48 loc) · 1.72 KB
/
Copy pathCsvHelper.cs
File metadata and controls
55 lines (48 loc) · 1.72 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
using Microsoft.VisualBasic.FileIO;
using System.Reflection;
using System.Text;
namespace BytecodeApi.CsvParser;
internal static class CsvHelper
{
public static TextFieldParser CreateTextFieldParser(Stream stream, string delimiter, Encoding? encoding, bool leaveOpen, out FieldInfo lineNumberField)
{
TextFieldParser parser = new(stream, encoding ?? Encoding.UTF8, encoding == null, leaveOpen)
{
TextFieldType = FieldType.Delimited,
TrimWhiteSpace = true,
Delimiters = [delimiter]
};
// The only way to retrieve the file line number:
// * Using a counter does not count empty lines
// * TextFieldParser.LineNumber points to the next line and returns -1 for the last line
lineNumberField = typeof(TextFieldParser).GetField("m_LineNumber", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw Throw.InvalidOperation("Field 'm_LineNumber' not found.");
return parser;
}
public static IEnumerable<CsvRow> EnumerateTextFieldParser(TextFieldParser parser, bool ignoreEmptyLines)
{
while (!parser.EndOfData)
{
CsvRow? csvRow = null;
try
{
string[] row = parser.ReadFields() ?? Array.Empty<string>();
if (!ignoreEmptyLines || !row.All(column => column == ""))
{
csvRow = new(row);
}
}
catch (MalformedLineException)
{
csvRow = new() { ErrorLine = parser.ErrorLine };
}
if (csvRow != null)
{
yield return csvRow;
}
}
}
public static void AutoDetectDelimiter(CsvDelimiterDetector delimiterDetector, Stream stream, Encoding? encoding, [NotNull] ref string? delimiter)
{
delimiter ??= delimiterDetector.FromStream(stream, encoding) ?? throw Throw.Format("The CSV delimiter could not be detected.");
}
}