【问题标题】:using streamReader class to read text file with dynamic number of columns in c#在c#中使用streamReader类读取具有动态列数的文本文件
【发布时间】:2012-12-06 10:11:44
【问题描述】:
 public class myRows
        {
            public decimal Col1 { get; set; }
            public decimal Col2 { get; set; }
            public decimal Col3 { get; set; }
            public decimal Col4 { get; set; }
            public decimal Col5 { get; set; }
            public decimal Col6 { get; set; }
            public string myDateTimeCol { get; set; }

            public myRows(string str)
            {
                var fields = str.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

                Col1 = Convert.ToDecimal(fields[0]);
                Col2 = Convert.ToDecimal(fields[1]);
                Col3 = Convert.ToDecimal(fields[2]);
                Col4 = Convert.ToDecimal(fields[3]);
                Col5 = Convert.ToDecimal(fields[4]);
                Col6 = Convert.ToDecimal(fields[5]);
                myDateTimeCol = string.Format("{0} {1} {2} {3} {4}", fields[6], fields[7], fields[8], fields[9], fields[10]);
            }
        }

然后我像阅读我的日志文件

var rows = new List<myRows>();
var sr = new StreamReader(txtFileToImport.Text);

while (!sr.EndOfStream)
       {
          string s = sr.ReadLine();
           if (!String.IsNullOrEmpty(s.Trim()))
               {
                  rows.Add(new myRows(s));
                }
        }

sr.Close();
dataGridView_preView.DataSource = rows;

这段代码面临的问题是,如果输入的 LogFile 有超过 12 列或更多列,我会得到 index out of range 异常

有没有我可以重构代码以使其处理具有任意数量列的任何 LogFile。要处理的日志文件有不​​同数量的列,我唯一的保证是日期列在所有情况下始终是最后一列。

【问题讨论】:

  • 您可以将它们读入List&lt;string&gt;,而不是将行读入类中,因此整个表存储在List&lt;List&lt;string&gt;&gt;
  • 您是否也负责创建日志文件?如果没有 - 有任何规格吗?
  • @mbx,我不负责创建日志文件。日志文件由监控发电机的专有软件系统创建。
  • IC,然后我将使用 List 并结合到最后五个字段为 DateTime.TryParse。如果您已经有基于 CSV 的日志处理,那么简单的转换和使用已经测试过的代码也是一种选择。由于您没有任何规范,您所能做的就是收集任何新样本来自己构建/重新设计一个。然后这些选择样本将成为您测试用例的一部分。

标签: c# winforms streamreader


【解决方案1】:

在不使用任何列表的情况下,我有一个完全不同的方法。请原谅编码,这只是一个快速测试。

首先,我将使用 DataTable。

public DataTable dt = new DataTable();

我从每一行读取的数据将存储在一个字符串类型的数组中。

public string[] data;

我们需要做的第一件事是确定数据文件中有多少列。下面我统计实例数,然后生成新的所需列数。

public void addcolumns()
        {

            using (StreamReader reader = new StreamReader(@"C:\DataColumnTest.txt"))
            {
                string s = reader.ReadLine();
                string[] col = s.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);


                foreach (var a in col)
                {
                    dt.Columns.Add(new DataColumn());
                }
            }
        }

接下来,要在哪里添加我们的 DataTable 的行。我们的行数据中的列数应该始终与我们的 DataTable 中的列数相匹配,并且在最初执行此操作时它应该每次都有效:-

Public void addRows()
    {
        var sr = new StreamReader(@"C:\DataColumnTest.txt");

        while (!sr.EndOfStream)
        {
            string s = sr.ReadLine();
            if (!String.IsNullOrEmpty(s.Trim()))
            {
                data = null;
                data = s.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                dt.Rows.Add(data);
            }

        }

        sr.Close();
    }

我为这个快速示例所做的只是在表单加载中调用这些方法,然后为 DataGrid 添加数据源:-

 private void Form1_Load(object sender, EventArgs e)
        {

            addcolumns();
            addRows();
            dataGridView1.DataSource = dt;
        }

我知道会有更简洁的方法来做到这一点,但它确实有效,与我看到的其他示例不同。

希望这会有所帮助。

*** 编辑 ****

这是我使用的数据以及结果。

【讨论】:

  • 我得到“输入数组长于该表中的列数”异常。
  • 检查您的代码,逐步执行 AddColumns 方法,错误在于构建列,我已经对其进行了测试,对我来说很好。
  • 请查看我的编辑。您可以看到它对我有用。现在让我如果你仍然卡住。
【解决方案2】:

试试这个:

public class myRows
        {
            public List<decimal> Cols = new List<decimal>();
            public string myDateTimeCol { get; set; }
            public string myVariableCols {
               get{
                  var sb = new StringBuilder();
                  for (var x = 0; x < Cols.length; x++){
                     sb.Append( Cols[x].ToString() );
                     if (x < Cols.length - 1) sb.Append("   ");
                  }
                  return sb.ToString();
               }
            }

            public myRows(string str)
            {
                var fields = str.Split(new[]{' '}, StringSplitOptions.RemoveEmptyEntries);
                int x;
                for (x = 0; x < fields.length-5;x++){
                   decimal d;
                   if (Decimal.TryParse(fields[x], out d)){
                      Cols.Add(d);
                   }
                }
                myDateTimeCol = string.Format("{0} {1} {2} {3} {4}", fields[x++], fields[x++], fields[x++], fields[x++], fields[x++]);
            }
        }

如果大于 4,这应该适用于任何列大小。 在您的数据网格中,您将只有两个数据绑定列:“myVariableCols”和“myDateTimeCol”。

【讨论】:

  • 快到了,但 logFile 中的所有可用列都作为一个 myVariableCols 列。有没有办法可以修改此代码并将这些列作为不同的字段/列返回。
  • 嗯,问题是您不知道确切的列数。解决方法是将datagrid设置为autogeneratecolumns="True",然后绑定到动态数据源,可能是List>;现在,您必须确保任何行(例如 List)具有相同的长度,因此您必须在数据绑定之前在行之间循环并将空填充字符串添加到较短的行,直到它们达到最长的长度收藏中的行。
猜你喜欢
  • 2013-04-20
  • 2013-01-15
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-14
相关资源
最近更新 更多