78 lines
2.2 KiB
C#
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;
|
|
}
|
|
}
|