Что касается значений заголовка документа, ваш код кажется функциональным, но просто для забавы я нашел регулярное выражение, которое выполняет эту работу. Затем я также отвечаю на вопрос о данных таблицы.
int textArrayPosition = 0; // Just to separate the header part and the table part
var headersDictionary = new Dictionary<string, string>();
List<string> arrayHeaders;
List<List<string>> arrayData = new List<List<string>>();
var headersFinder = new Regex(@"^(.*?) {2,}(.*)\r\n\-*? {2,}\-*\r\n(.*?)( {2,}(.*)|$)", RegexOptions.Multiline);
foreach (Match match in headersFinder.Matches(inputText))
{
if (match.Groups.Count < 4)
continue;
var firstHeaderName = match.Groups[1].Value;
var secondHeaderName = match.Groups[2].Value;
if (!string.IsNullOrWhiteSpace(firstHeaderName))
headersDictionary.Add(firstHeaderName, match.Groups[3].Value);
if (!string.IsNullOrWhiteSpace(secondHeaderName))
{
if (match.Groups.Count == 6)
headersDictionary.Add(secondHeaderName, match.Groups[5].Value);
else
headersDictionary.Add(secondHeaderName, string.Empty);
}
textArrayPosition = match.Index + match.Length;
}
Console.WriteLine("*** Document headers :");
foreach (var entry in headersDictionary)
Console.WriteLine($"{entry.Key} = {entry.Value}");
Затем мы находим таблицу в вашем тексте в виде списка строк.
var arrayLines = inputText.Substring(textArrayPosition).Split(new string[] { "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);
Таким образом, мы обрабатываем таблицуТак как заголовки таблицы не позволяют разделять столбцы, я основывался на том факте, что в первой строке данных было найдено как минимум 2 последовательных пробела, чтобы можно было угадать положение столбцов. Простое регулярное выражение помогает нам сделать это.
if (arrayLines.Length > 2)
{
var arrayColsPositions = new List<int>();
// Find cols positions
arrayColsPositions.Add(0);
var firstDataLine = arrayLines[2];
var columnsPositionDetector = new Regex(@" {2,}", RegexOptions.Singleline);
foreach (Match match in columnsPositionDetector.Matches(firstDataLine))
{
arrayColsPositions.Add(match.Index + match.Length);
}
// Find headers
arrayHeaders = ReadLineValues(arrayLines[0], arrayColsPositions).ToList();
// Find data lines
for (int lineId = 2; lineId < arrayLines.Length; lineId++)
{
arrayData.Add(ReadLineValues(arrayLines[lineId], arrayColsPositions).ToList());
}
Console.WriteLine("\n*** Array headers :");
Console.WriteLine(string.Join(", ", arrayHeaders));
Console.WriteLine("\n*** Array lines data :");
foreach (var record in arrayData)
{
Console.WriteLine(string.Join(", ", record));
}
}
else
Console.WriteLine("The array is empty.");
Наконец, вот небольшой полезный метод, который я разработал для удобного поиска, без превышения длины определенных строк, данных в нужном месте.
private static IEnumerable<string> ReadLineValues(string sourceLine, List<int> colsPositions)
{
for (int colId = 0; colId < colsPositions.Count; colId++)
{
var start = colsPositions[colId];
int length;
if (colId < colsPositions.Count - 1)
length = colsPositions[colId + 1] - start;
else
length = sourceLine.Length - start;
if (start < sourceLine.Length)
{
if (start + length > sourceLine.Length)
length = sourceLine.Length - start;
yield return sourceLine.Substring(start, length).Trim();
}
}
}