Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# c中分割CSV文件的有效方法#_C#_.net_Performance_Linq - Fatal编程技术网

C# c中分割CSV文件的有效方法#

C# c中分割CSV文件的有效方法#,c#,.net,performance,linq,C#,.net,Performance,Linq,我正试图根据账单中的电话号码,将一个巨大的电信账单拆分为一个CSV文件,300MB static void FileSplitWriter(List<SplitFile> pList, string info) { pList.ForEach(delegate(SplitFile per) { int startingLine = per.startingLine; int ending

我正试图根据账单中的电话号码,将一个巨大的电信账单拆分为一个CSV文件,300MB

    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();
        });


    }
有些电话号码的账单是20行,有些超过1000行,所以它是动态的。在第一次通过时,我阅读了账单,并使用LINQ根据电话号码对账单进行分组,并计算CSV文件中每个电话号码账单包含的行数。然后插入一个列表:拆分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();
        });


    }
static void FileSplitWriter(列表pList,字符串信息)
{
pList.ForEach(委托(每个拆分文件)
{
int startingLine=per.startingLine;
int endingLine=per.endingLine;
字符串[]fileContents=File.ReadAllLines(信息);
var query=fileContents.Skip(startingLine-1).Take(endingLine-(startingLine-1));
字符串directoryPath=Path.GetDirectoryName(info);
字符串filenameok=Path.GetFileNameWithoutExtension(info);
StreamWriter ffs=新的StreamWriter(目录路径+“\\”+文件名OK+“\\拆分”+per.id+“.csv”);
foreach(查询中的字符串行)
{
自由流速度写线(行);
}
ffs.Dispose();
ffs.Close();
});
}

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

我建议您使用现有的众多快速CSV解析库之一


代码项目和其他地方都发布了这些文件。

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

 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();
    });
}
static void FileSplitWriter(列表pList,字符串信息){
字符串[]fileContents=File.ReadAllLines(信息);
字符串directoryPath=Path.GetDirectoryName(info);
字符串filenameok=Path.GetFileNameWithoutExtension(info);
pList.ForEach(委托(每个拆分文件){
int startingLine=per.startingLine;
int endingLine=per.endingLine;
var query=fileContents.Skip(startingLine-1).Take(endingLine-(startingLine-1));
StreamWriter ffs=新的StreamWriter(目录路径+“\\”+文件名OK+“\\拆分”+per.id+“.csv”);
foreach(查询中的字符串行){
自由流速度写线(行);
}
ffs.Close();
ffs.Dispose();
});
}

这段代码中最低效的部分似乎是您多次将整个300MB文件读入内存。你应该只需要读一次

  • 将文件读入可枚举的数据结构
  • 按电话号码分组
  • 循环每个组并将每个组写入文件

  • 注意:如果您使用的是.NET 4.0,您可能会通过使用
    File.ReadLines()
    (而不是ReadAllLines)获得一些内存效率。

    而不是
    ffs.Dispose()
    为什么不使用
    语句呢?为什么要将整个文件读入循环中的内存?@dasblinkenlight抱歉。我将信息作为试图拆分的文件名传递。如果您给出输入和所需输出的示例,将更容易帮助您。也许您应该在调用
    Dispose
    (关于
    ffs
    )之前调用
    Close
    。@RonKlein Great catch!非常感谢你!