【问题标题】:Parse text file and assign parts to columns解析文本文件并将部分分配给列
【发布时间】:2010-06-24 15:30:59
【问题描述】:

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

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

    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 列都写一行?

非常感谢任何帮助!

【问题讨论】:

    标签: c# parsing text variable-assignment


    【解决方案1】:

    最简单的方法是将 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);
    }
    

    【讨论】:

      【解决方案2】:

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

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

      (注意,那是“航空代码”。)

      【讨论】:

        【解决方案3】:

        您可以使用FileHelpers library

        【讨论】:

          【解决方案4】:

          你可以这样做

          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 语句。如果它们确实必须单独命名,那么我认为您将不得不使用反射来获取对应于 columns[ix] 的每一列的实例成员。

          我不确定,但 AutoMapper 可能会处理类似的事情。你可以调查一下。

          【讨论】:

            【解决方案5】:

            .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
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-02-28
              • 1970-01-01
              • 1970-01-01
              • 2018-09-03
              • 2012-10-09
              • 2017-01-10
              • 1970-01-01
              • 2015-02-28
              相关资源
              最近更新 更多