Files
LehrerApp/LehrerApp.Core/Importing/DelimitedTextParser.cs
T

78 lines
2.2 KiB
C#

using System.Text;
namespace LehrerApp.Core.Importing;
internal sealed record DelimitedRecord(int LineNumber, IReadOnlyList<string> Fields);
internal static class DelimitedTextParser
{
public static bool TryParse(
string text,
char delimiter,
out List<DelimitedRecord> records,
out string? error)
{
records = [];
error = null;
var fields = new List<string>();
var field = new StringBuilder();
var inQuotes = false;
var line = 1;
var recordStartLine = 1;
for (var index = 0; index < text.Length; index++)
{
var current = text[index];
if (current == '"')
{
if (inQuotes && index + 1 < text.Length && text[index + 1] == '"')
{
field.Append('"');
index++;
}
else
{
inQuotes = !inQuotes;
}
continue;
}
if (current == delimiter && !inQuotes)
{
fields.Add(field.ToString());
field.Clear();
continue;
}
if ((current == '\r' || current == '\n') && !inQuotes)
{
if (current == '\r' && index + 1 < text.Length && text[index + 1] == '\n')
index++;
fields.Add(field.ToString());
field.Clear();
records.Add(new DelimitedRecord(recordStartLine, fields.ToList()));
fields.Clear();
line++;
recordStartLine = line;
continue;
}
if (current == '\n') line++;
field.Append(current);
}
if (inQuotes)
{
error = $"Ein Textfeld ab Zeile {recordStartLine} besitzt kein schließendes Anführungszeichen.";
return false;
}
if (field.Length > 0 || fields.Count > 0)
{
fields.Add(field.ToString());
records.Add(new DelimitedRecord(recordStartLine, fields.ToList()));
}
return true;
}
}