在c#中拆分CSV文件的有效方法

时间:2011-12-10 12:33:05

标签: c# .net performance linq

我正在尝试将一个大型电信账单拆分为CSV文件,根据账单中的电话号码将300MB分成较小的块。

有些电话号码有20行,有些有超过1000行,所以它是动态的。在第一次通过时,我阅读账单并使用LINQ按电话号码对它们进行分组,并计算CSV文件中每个电话号码计费的账单所包含的行数。然后插入List:split_id,起始行,结束行。 (起始线从0开始)。

以下脚本是我用来拆分较小账单的。但是这300MB拥有超过7500个电话号码,即使每个文件都低于100KB,也需要永远处理拆分账单。

    static void FileSplitWriter(List<SplitFile> pList, string info)
    {

        pList.ForEach(delegate(SplitFile per)
        {
            int startingLine = per.startingLine;
            int endingLine = per.endingLine;
            string[] fileContents = File.ReadAllLines(info);
            var query = fileContents.Skip(startingLine - 1).Take(endingLine - (startingLine - 1));
            string directoryPath = Path.GetDirectoryName(info);
            string filenameok = Path.GetFileNameWithoutExtension(info);

            StreamWriter ffs = new StreamWriter(directoryPath + "\\" + filenameok + "_split" + per.id + ".csv");
            foreach (string line in query)
            {
                ffs.WriteLine(line);
            }
            ffs.Dispose();
            ffs.Close();
        });


    }

我的问题是,这个过程是否有可能更快/更有效?按照目前的速度,单独拆分文件需要3个小时左右。

3 个答案:

答案 0 :(得分:3)

看起来此代码中效率最低的部分是您将整个300MB文件读入内存多次次。你应该只需要阅读一次......

  1. 将文件读入一些可枚举的数据结构。
  2. 按电话号码分组。
  3. 遍历每个组并将每个组写入文件。
  4. 注意:如果您使用的是.NET 4.0,则可以使用File.ReadLines()(而不是ReadAllLines)来提高内存效率。

答案 1 :(得分:2)

我建议您使用存在的许多快速CSV解析库之一。

在代码项目和其他地方发布了several个,以及filehelpers

答案 2 :(得分:2)

尝试将文件的读取移动到循环外部:

 static void FileSplitWriter(List<SplitFile> pList, string info) {
    string[] fileContents = File.ReadAllLines(info);
    string directoryPath = Path.GetDirectoryName(info);
    string filenameok = Path.GetFileNameWithoutExtension(info);
    pList.ForEach(delegate(SplitFile per) {
        int startingLine = per.startingLine;
        int endingLine = per.endingLine;
        var query = fileContents.Skip(startingLine - 1).Take(endingLine - (startingLine - 1));
        StreamWriter ffs = new StreamWriter(directoryPath + "\\" + filenameok + "_split" + per.id + ".csv");
        foreach (string line in query) {
            ffs.WriteLine(line);
        }
        ffs.Close();
        ffs.Dispose();
    });
}