C# c中分割CSV文件的有效方法#
我正试图根据账单中的电话号码,将一个巨大的电信账单拆分为一个CSV文件,300MBC# 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
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!非常感谢你!