Разобрать текстовый файл и назначить детали столбцам - PullRequest
0 голосов
/ 24 июня 2010

Я получаю текстовый файл с разделителями табуляции, который необходимо проанализировать.После анализа детали должны быть назначены определенным столбцам.

Вот пример кода, который я использую для этого:

    string path = "C:\\Users\\Robert\\Desktop\\Test.txt";

    FileInfo fileInfo = new FileInfo(path);

    using (StreamReader streamReader = fileInfo.OpenText())
    {
        string line = "";

        while ((line = streamReader.ReadLine()) != null)
        {
            string[] columns = line.Split('\t');

            Output0Buffer.AddRow();
            Output0Buffer.Column0 = columns[0];
            Output0Buffer.Column1 = columns[1];
            Output0Buffer.Column2 = columns[2];
            Output0Buffer.Column3 = columns[3];
            Output0Buffer.Column4 = columns[4];
        }
    }

Проблема в том, что некоторые изстроки в текстовом файле не имеют 5 столбцов, и этот код завершается неудачно, когда он пытается присвоить Column4 значение столбцов [4] (на самом деле мой настоящий файл состоит из 21 части, поэтому он более подвержен сбоям).

Как можно переписать это, чтобы присвоить значения столбцу 4 (5,6 - 21) только при наличии фактических данных?Кроме того, можно ли это записать в цикл for или foreach, чтобы сделать его немного более аккуратным, поэтому мне не нужно иметь строку для всех 21 столбца?

Любая помощь очень ценится!

Ответы [ 5 ]

3 голосов
/ 24 июня 2010

Самое простое - добавить коллекцию Columns в тип выходного буфера, а затем установить значения в цикле for, например:

for(int i = 0; i < columns.Length; i++)
{
    Output0Buffer.Columns[i] = columns[i];
}

Если вы не можете изменить этот тип и соглашение об именах свойствявляется последовательным (то есть столбец 1,2,3 ... n), то вы можете установить каждое свойство, хотя отражение:

Type buffType = Output0Buffer.GetType();
for(int i = 0; i < columns.Length; i++)
{
    string propertyName = String.Format("Column{0}", i);
    PropertyInfo pi = buffType.GetProperty(propertyName);
    pi.SetValue(buffer, columns[i], null);
}
1 голос
/ 24 июня 2010

Вы не сообщили нам определение Output0Buffer, но наиболее очевидным решением было бы изменить его определение, чтобы разрешить индексацию, например:

int maxCol = Math.Min(columns.Length,Output0Buffer.Columns.Count);
for(int colIDx=0;colIdx<maxCol;++colIdx)
   Output0Buffer.Columns[colIdx]=columns[colIdx];

(Осторожно, это был "воздушный кодекс").)

0 голосов
/ 24 июня 2010

Существует перегрузка на .Split(...), которую вы можете попытаться использовать.

string[] columns = (line + "\t\t\t\t").Split(new [] {'\t'}, 5);

Output0Buffer.AddRow();
Output0Buffer.Column0 = columns[0];
Output0Buffer.Column1 = columns[1];
Output0Buffer.Column2 = columns[2];
Output0Buffer.Column3 = columns[3];

// The trim is needed on this line because the split method
// will stop processing after it has hit the number of elements
// listed in the count value
Output0Buffer.Column4 = columns[4].TrimEnd('\t'); 

... Другой вариант будет выглядеть примерно так ...

var parts = line.Split('\t');
var columns = new string[5];
if (parts.Length > columns.Length)
    throw new InvalidOperationException();
Array.Copy(parts, columns, parts.Length);

// the rest of your code goes here
0 голосов
/ 24 июня 2010

Вы можете сделать что-то вроде

Output0Buffer.AddRow()
for (ix = 0; ix < column.Length; ix++)
{
    switch(ix)
    { case 0:
        Output0Buffer.Column0 = columns[ix];
        break;
      case 1:
        ...
    }
}

Названы ли столбцы в вашем OutputBuffer как Column0, Column1 и т. Д.?Есть ли причина, по которой они не могут быть массивом?Если бы они могли быть, то вы могли бы заменить

    Output0Buffer.Columns[ix] = columns[ix];

на весь оператор switch выше.Если они должны иметь индивидуальное имя, то я думаю, что вам нужно будет использовать отражение, чтобы получить элемент экземпляра для каждого столбца, который соответствует столбцам [ix].

Я не уверен, но возможно, чтоAutoMapper может обрабатывать что-то подобное.Вы можете исследовать это.

0 голосов
/ 24 июня 2010

Вы можете использовать библиотеку FileHelpers .

...