StreamReader跳过Null或WhiteSpace线的最佳方式

时间:2015-08-15 03:02:45

标签: c# csv streamreader

在搜索并尝试了我发现的不同方式之后,我或者对我编写代码的方式感到满意,或者它对我来说并不适合。我是编程新手,所以我的理解是有限的。请记住答案。

我想逐行读取.csv文件并跳过空白行。用我想要放入对象列表的行的内容。我有一切工作,除了跳绳部分。此外,任何有关改进我的代码的任何部分的反馈都是受欢迎的。我喜欢建设性的批评。

public void CardaxCsvFileReader()
    {
        string cardaxCsvPath = (@"C:\Cardax2WkbTest\Cardax\CardaxTable.csv");

        try
        {
            using (System.IO.StreamReader cardaxSR =
                new System.IO.StreamReader(System.IO.File.OpenRead(cardaxCsvPath)))
            {
                string line = "";
                string[] value = line.Split(',');

                while (!cardaxSR.EndOfStream)
                {                              // this commented out part is what I would like to work but doesn't seem to work.
                    line = cardaxSR.ReadLine();//.Skip(1).Where(item => !String.IsNullOrWhiteSpace(item));
                    value = line.Split(',');

                    if (line != ",,,,,") // using this as temp to skip the line because the above commented out part doesn't work.
                    {
                    CardaxDataObject cardaxCsvTest2 = new CardaxDataObject();

                    cardaxCsvTest2.EventID = Convert.ToInt32(value[0]);
                    cardaxCsvTest2.FTItemID = Convert.ToInt32(value[1]);
                    cardaxCsvTest2.PayrollNumber = Convert.ToInt32(value[2]);
                    cardaxCsvTest2.EventDateTime = Convert.ToDateTime(value[3]);
                    cardaxCsvTest2.CardholderFirstName = value[4];
                    cardaxCsvTest2.CardholderLastName = value[5];

                    Globals.CardaxQueryResult.Add(cardaxCsvTest2);
                    }
                }
            }
        }
        catch (Exception)
        {
            myLog.Error("Unable to open/read Cardax simulated punch csv file! " +
                "File already open or does not exist: \"{0}\"", cardaxCsvPath);
        }

3 个答案:

答案 0 :(得分:0)

只需检查是否value.Length == 6,这样就会跳过没有足够数据列的行

答案 1 :(得分:0)

<强> EDITED

如果您的行不是真正空白且包含逗号,则可以使用RemoveEmptyEntries选项进行拆分,然后检查列数。

                while (!cardaxSR.EndOfStream)
                {                              // this commented out part is what I would like to work but doesn't seem to work.
                    line = cardaxSR.ReadLine();//.Skip(1).Where(item => !String.IsNullOrWhiteSpace(item));
                    value = line.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries);  // <-- Remove empty columns while splitting. It has a side-effect: Any record with just a single blank column will also get discarded by the if that follows.
                    if (value.length < 6)
                      continue;

                    CardaxDataObject cardaxCsvTest2 = new CardaxDataObject();

                    cardaxCsvTest2.EventID = Convert.ToInt32(value[0]);
                    cardaxCsvTest2.FTItemID = Convert.ToInt32(value[1]);
                    cardaxCsvTest2.PayrollNumber = Convert.ToInt32(value[2]);
                    cardaxCsvTest2.EventDateTime = Convert.ToDateTime(value[3]);
                    cardaxCsvTest2.CardholderFirstName = value[4];
                    cardaxCsvTest2.CardholderLastName = value[5];

                    Globals.CardaxQueryResult.Add(cardaxCsvTest2);
                }

我的另一个改进反馈:当您捕获异常时,除了自定义错误行之外,最好记录异常。自定义错误行可能对网站用户说好,但作为运行某些服务的开发人员,您会欣赏实际的异常堆栈跟踪。它将帮助您更轻松地调试错误。

    catch (Exception ex)
    {
        myLog.Error("Unable to open/read Cardax simulated punch csv file! " +
            "File already open or does not exist: \"{0}\".\r\n Exception: {1}", cardaxCsvPath, ex.ToString());
    }

答案 2 :(得分:0)

使用专用CSV解析器,例如此处提供的EasyCSV类 *

  

https://github.com/jcoehoorn/EasyCSV

public void CardaxCsvFileReader()
{
    try 
    {
        string cardaxCsvPath = (@"C:\Cardax2WkbTest\Cardax\CardaxTable.csv");
        Globals.CardaxQueryResult =
           EasyCSV.FromFile(cardaxCsvPath)
              .Where(r => r.Any(c => !string.IsNullOrEmpty(c)))
              .Select(r => CardaxDataObject() {
                    cardaxCsvTest2.EventID = int.Parse(r[0]),
                    cardaxCsvTest2.FTItemID = int.Parse(r[1]),
                    cardaxCsvTest2.PayrollNumber = int.Parse(r[2]),
                    cardaxCsvTest2.EventDateTime = DateTinme.Parse(r[3]),
                    cardaxCsvTest2.CardholderFirstName = r[4],
                    cardaxCsvTest2.CardholderLastName = r[5]
              }).ToList();      
    }
    catch (Exception)
    {
        myLog.Error("Unable to open/read Cardax simulated punch csv file! " +
            "File already open or does not exist: \"{0}\"", cardaxCsvPath);
    }
}

我还建议重新思考如何构建它。以下代码是更好的做法:

public IEnumerable<CardaxDataObject> ReadCardaxCsvFile(string filename)
{
   //no try block at this level. Catch that in the method that calls this method

    return EasyCSV.FromFile(cardaxCsvPath)
          .Where(r => r.Any(c => !string.IsNullOrEmpty(c)))
          // You may want to put a try/catch inside the `Select()` projection, though.
          // It would allow you continue if you fail to parse an individual record
          .Select(r => CardaxDataObject() {
                cardaxCsvTest2.EventID = int.Parse(r[0]),
                cardaxCsvTest2.FTItemID = int.Parse(r[1]),
                cardaxCsvTest2.PayrollNumber = int.Parse(r[2]),
                cardaxCsvTest2.EventDateTime = DateTinme.Parse(r[3]),
                cardaxCsvTest2.CardholderFirstName = r[4],
                cardaxCsvTest2.CardholderLastName = r[5]
         });      
}

突然间,这个方法归结为一个陈述(尽管是一个很长的陈述)。像这样的代码更好,因为它更强大,原因有三:它不仅限于使用一个输入文件,它不仅限于将它的输出发送到一个位置,而且不受限制只有一种方法来处理错误。你会这样称呼它:

try 
{
    string cardaxCsvPath = (@"C:\Cardax2WkbTest\Cardax\CardaxTable.csv");
    Globals.CardaxQueryResult = ReadCardaxCsvFile(cardaxCsvPath).ToList();
}
catch (Exception)
{
    myLog.Error("Unable to open/read Cardax simulated punch csv file! " +
            "File already open or does not exist: \"{0}\"", cardaxCsvPath);
}

或者像这样:

try 
{
    string cardaxCsvPath = (@"C:\Cardax2WkbTest\Cardax\CardaxTable.csv");
    foreach (var result in ReadCardaxCsvFile(cardaxCsvPath))
    {
        Globals.CardaxQueryResult.Add(result);
    }
}
catch (Exception)
{
    myLog.Error("Unable to open/read Cardax simulated punch csv file! " +
            "File already open or does not exist: \"{0}\"", cardaxCsvPath);
}

我还建议不要使用像这样的Globals类。找到一个更有意义的对象,您可以使用该对象关联此数据。

*免责声明:我是该解析器的作者