代码之家  ›  专栏  ›  技术社区  ›  user3150378

C#-通过删除坏行拆分CSV文件

  •  1
  • user3150378  · 技术社区  · 7 年前

    我有一个csv文件,有200万行,文件大小为2GB。但是由于有两个自由文本格式的列,这些列包含冗余的CRLF并导致文件无法加载到sqlserver表中。我得到一个错误,最后一列没有以“结束”。

    我有以下代码,但它在读取文件名时会出现OutOfMemoryException。这条线是:

    var lines = File.ReadAllLines(fileName);
    

    我该怎么修?理想情况下,我想把文件分为两个好的和坏的行。或删除不以“CRLF”结尾的行。

    int goodRow = 0;
    int badRow = 0;
    String badRowFileName = fileName.Substring(0, fileName.Length - 4) + "BadRow.csv";
    String goodRowFileName = fileName.Substring(0, fileName.Length - 4) + "GoodRow.csv";
    var charGood = "\"\"";
    String lineOut = string.Empty;
    
    String str = string.Empty;
    var lines = File.ReadAllLines(fileName);
    
    StringBuilder sbGood = new StringBuilder();
    StringBuilder sbBad = new StringBuilder();
    
    foreach (string line in lines)
    {
         if (line.Contains(charGood))
        {
            goodRow++;
            sbGood.AppendLine(line);
        }
        else
        {
            badRow++;
            sbBad.AppendLine(line);
        }
    }
    
    if (badRow > 0)
    {
        File.WriteAllText(badRowFileName, sbBad.ToString());
    }
    if (goodRow > 0)
    {
        File.WriteAllText(goodRowFileName, sbGood.ToString());
    }
    
    sbGood.Clear();
    sbBad.Clear();
    
    msg = msg + "Good Rows - " + goodRow.ToString() + " Bad Rows - " + badRow.ToString() + " Done.";
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   AtlSteve    7 年前

    我不建议将整个文件读入内存,然后处理文件,然后将所有修改的内容写入新文件。

            using (var rdr = new StreamReader(fileName))
            using (var wrtrGood = new StreamWriter(goodRowFileName))
            using (var wrtrBad = new StreamWriter(badRowFileName))
            {
                string line = null;
                while ((line = rdr.ReadLine()) != null)
                {
                    if (line.Contains(charGood))
                    {
                        goodRow++;
                        wrtr.WriteLine(line);
                    }
                    else
                    {
                        badRow++;
                        wrtrBad.WriteLine(line);
                    }
    
                }
            }
    
        2
  •  2
  •   Joel Coehoorn    7 年前

    你可以这样把代码翻译成 许多的

    int goodRow = 0, badRow = 0;
    String badRowFileName = fileName.Substring(0, fileName.Length - 4) + "BadRow.csv";
    String goodRowFileName = fileName.Substring(0, fileName.Length - 4) + "GoodRow.csv";
    
    var charGood = "\"\"";
    
    using (var lines = File.ReadLines(fileName))
    using (var swGood = new StreamWriter(goodRowFileName))
    using (var swBad = new StreamWriter(badRowFileName))
    {    
        foreach (string line in lines)
        {
            if (line.Contains(charGood))
            {
                goodRow++;
                swGood.WriteLine(line);
            }
            else
            {
                badRow++;
                swBad.WriteLine(line);
            }
        }
    }
    
    msg += $"Good Rows: {goodRow,9}   Bad Rows: {badRow,9} Done.";
    

    但我也会考虑使用 实csv解析器 为了这个。NuGet上有很多。这甚至可以让你在飞行中清理数据。