解析文本文件并将部件分配给列

时间:2010-06-24 15:31:00

标签: c# parsing text variable-assignment

我收到一个必须解析的制表符分隔的文本文件。解析后,必须将这些部分分配给特定的列。

以下是我用来执行此操作的代码示例:

    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个零件,所以这更容易失败)。

如果有实际数据,如何重写这个值只能为Column4(5,6 - 21)赋值?此外,是否可以将其写入for或foreach循环以使其更整洁,因此我不必为所有21列添加一行?

非常感谢任何帮助!

5 个答案:

答案 0 :(得分:3)

最简单的方法是将一个Columns集合添加到输出缓冲区类型,然后在for循环中设置值,例如

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

如果你不能改变那种类型并且属性命名约定是一致的(即column1,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 :(得分:1)

您没有告诉我们Output0Buffer的定义,但最明显的解决方案是更改其定义以允许这样的索引:

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

(小心,那是“航空代码”。)

答案 2 :(得分:0)

您可以使用FileHelpers library

答案 3 :(得分:0)

您可以执行类似

的操作
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可能会处理类似的事情。你可以调查一下。

答案 4 :(得分:0)

您可以尝试使用.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