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

2020-08-28  本文已影响0人  天空之城_2692

问题描述:需要将一个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了。可以根据自己电脑实际情况来。
改了之后再重新传,速度飞快。几千万行的绝对十分钟之内。

上一篇下一篇

猜你喜欢

热点阅读