美文网首页
C# 处理千万行csv文件读写

C# 处理千万行csv文件读写

作者: 天空之城_2692 | 来源:发表于2020-08-28 14:41 被阅读0次

    问题描述:需要将一个csv格式的表格文件转换成我想要的表格内容形式。(前四行的每个竖列转换成每行得横列,然后第五行得横列于前三行结合拼接成一行,类似这种得样式)


    待转格式 转换后

    最开始写的时候用的是Microsoft.Office.Interop.Excel库,挨个单元格读excel然后再挨个单元格写入文件,谁用谁知道,刚开始没用多大的文件就几兆大概转换完的时间要个半小时,但是我们这边需要转的竟然大多都是上百兆得文件,转换后粗滤算下需要两千多万行,excel文件最多也就只能有一百多万行。
    一次要转换几十个文件照这个速度要一周,得!重写。
    由于之前也写过一个读千万行的csv文件,与之不同的是,只要读,不要文件处理,每读五百行转换成json传给客户,用的StreamReader,由于我的excel要做文件处理,StreamReader是按行读,效率快但是想直接操作单元格数据还要自己处理,我就抱着试试心态重写了一份。利用StreamReader读,StreamWriter写。

             StringBuilder sbData = new StringBuilder();
                    StringBuilder nsbData = new StringBuilder();
                    string sbHeader = sb.ToString();
                    //sbData = sb;
                    System.IO.FileStream fs = null;
                    StreamWriter sw = null;
                    try
                    {
                        sbData.Append(sbHeader);
                        for (int k = 1; k <= (wsRows - paraLine); k++)//(wsRows - paraLine)
                        {
                            lineTxt = reader.ReadLine();
                            nLineCount++;
                            string[] split = lineTxt.Split(',');
                            for (int i = colTemp; i < wsColumns; i++)
                            {
                                if (split[i].ToString() == "")
                                {
                                    breakCount = breakCount +( wsColumns - split.Length-1);
                                    break;
                                }
                                if (float.Parse(split[i].ToString()) <= float.Parse(d[i].ToString()) && (float.Parse(split[i].ToString()) >= float.Parse(c[i].ToString())))
                                {
                                    testResult = "PASS";
                                }
                                else
                                {
                                    testResult = "FAIL";
                                }
    
                                sbData.Append("***\t");
                                sbData.Append("*****\t");
                                sbData.Append("******D3\t");
                                sbData.Append(barName + "\t");
                                sbData.Append(barCode + "\t");
                                sbData.Append(k + "\t");
                                sbData.Append("\t");
                                sbData.Append("\t");
                                sbData.Append(processBatch + "\t");
                                sbData.Append(productLine + "\t");
                                sbData.Append(testEquip + "\t");
                                sbData.Append(testTime + "\t");
                                sbData.Append(testType + "\t");
                                sbData.Append(testProcess + "\t");
                                sbData.Append(a[i].ToString() + "\t");
                                sbData.Append(testCondition + "\t");
                                sbData.Append(c[i].ToString() + "\t");
                                sbData.Append(d[i].ToString() + "\t");
                                sbData.Append(b[i].ToString() + "\t");
                                sbData.Append(split[i].ToString() + "\t");
                                sbData.Append("\t");
                                sbData.Append(testResult + "\t");
                                sbData.Append("\t");
                                sbData.Append(Environment.NewLine);
    
                                dataLineCount++;
                                backgroundWorker1.ReportProgress(k * 100 / (wsRows - paraLine), "正在转换文件:" + "..\\" + fileName);//(dataLineCount * 100) / ((wsRows - paraLine) * (wsColumns - 6)-breakCount)
                                if (dataLineCount % 800000 == 0)//每80万行写入一个文件
                                {
                                    m_strSavePath = m_strFullFilePath + "\\" + "ic***-****-***-" + productName + "-" + customerLotNo + "-" + processBatch + "-" + DateTime.Now.ToString("yyyyMMddhhmmssfff") + "-" + fileCount + ".csv";
                                    fs = new FileStream(m_strSavePath, System.IO.FileMode.Create, System.IO.FileAccess.Write);
                                    sw = new StreamWriter(fs, new System.Text.UnicodeEncoding());
                                    sw.Write(sbData.ToString());
                                    sw.Flush();
                                    sw.Close();
                                    sw.Dispose();
                                    sbData.Clear();
                                    sbData.Append(sbHeader);
                                    fileCount++;
                                }
                            }
                        }
                    }
    

    核心就是按照行读,再把自己数据处理成一行,再按照行写。
    遇到的问题就是内存溢出,由于数据量大,转换速度快,一开始打算每读一百万行保存成一个文件,但是电脑配置有限,该成八十万就ok了。可以根据自己电脑实际情况来。
    改了之后再重新传,速度飞快。几千万行的绝对十分钟之内。

    相关文章

      网友评论

          本文标题:C# 处理千万行csv文件读写

          本文链接:https://www.haomeiwen.com/subject/xcdlsktx.html