C# 将一个文件拆分为多个小文件的优化
我试图将一个大文件(逗号分隔,每个术语用双引号括起来)拆分为许多较小的文件,根据每个记录中的第一项键,通常有多个记录具有相同的键 这个大文件的大小可以从1GB到2GB,生成的文件数量可以从10000到30000,每个文件位于以密钥命名的子文件夹中 在C#中,我在每一行上执行StreamReader.ReadLine(),将结果连接到不同的键(向上一个键发送最后一个数据的信号),然后调用函数异步写入文件。我正在调用windows sort对这些文件进行排序,以使密钥连续(因此我只需打开文件一次),但操作仍然需要大约20分钟才能完成。有没有办法加快速度C# 将一个文件拆分为多个小文件的优化,c#,file-io,io,text-parsing,C#,File Io,Io,Text Parsing,我试图将一个大文件(逗号分隔,每个术语用双引号括起来)拆分为许多较小的文件,根据每个记录中的第一项键,通常有多个记录具有相同的键 这个大文件的大小可以从1GB到2GB,生成的文件数量可以从10000到30000,每个文件位于以密钥命名的子文件夹中 在C#中,我在每一行上执行StreamReader.ReadLine(),将结果连接到不同的键(向上一个键发送最后一个数据的信号),然后调用函数异步写入文件。我正在调用windows sort对这些文件进行排序,以使密钥连续(因此我只需打开文件一次),
sfd = new SaveFileDataDelegate(this.SaveFileData);
private void CSVParse(string filename, string unzippedFilePath, string feedname)
{
StreamReader filestream = null;
FileStream readerStream = null;
try
{
readerStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.None, 120000, FileOptions.SequentialScan);
filestream = new StreamReader(readerStream, Encoding.UTF8, false, 120000);
string tempstring = "";
string buffer = "";
string lastlotkey = "";
IAsyncResult result = null;
activityLog.Log("Parsing File: " + filename);
while (((tempstring = filestream.ReadLine()) != null) || buffer != "")
{
if (tempstring == null)
{
tempstring = "";
}
string lotkey = tempstring.Replace("\"","").Split(',').First();
if (lotkey == tempstring && tempstring != "")
{
break;
}
if (lotkey == "DealerID")
{
continue;
}
if (lastlotkey == "")
{
lastlotkey = lotkey;
}
if ((lotkey != lastlotkey && buffer.Length > 0))
{
result = sfd.BeginInvoke(outputDirectory + @"\" + feedname + @"\" + lastlotkey + @"\" + (filename.Split('\\').Last()).Split('.').First() + ".txt", buffer, outputDirectory + @"\" + feedname + @"\" + lastlotkey,null,null);
lastlotkey = lotkey;
buffer = "";
if (tempstring == "")
{
continue;
}
}
if (buffer.Length > 0)
{
buffer = buffer + "\r\n";
}
buffer = buffer + tempstring;
}
filestream.Close();
readerStream.Close();
if (result != null)
{
result.AsyncWaitHandle.WaitOne(-1);
}
return;
}
catch (Exception e)
{
activityLog.Log("Error Occurred: " + e.ToString());
if (filestream != null)
{
filestream.Close();
}
hadError = true;
return;
}
}
private void SaveFileData(string file, string buffer, string directory)
{
// create file from last lot key with data from parsing, write, close, update lastlotkey
Directory.CreateDirectory(directory);
FileStream fs = null;
StreamWriter temp = null;
try
{
if (!File.Exists(file))
{
fs = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, 120000);
}
else
{
fs = new FileStream(file, FileMode.Truncate, FileAccess.Write, FileShare.None, 120000);
}
temp = new StreamWriter(fs, Encoding.UTF8, 120000);
temp.AutoFlush = false;
temp.WriteLine(headerLine);
temp.Write(buffer);
temp.Flush();
temp.Close();
fs.Close();
}
catch (Exception e)
{
activityLog.Log("Error Occurred: " + e.ToString());
if (fs != null)
{
fs.Close();
}
if (temp != null)
{
temp.Close();
}
hadError = true;
return;
}
}
编辑
我对堆栈溢出和internet最深处进行了爬网,在逐行分析之后,我发现字符串连接实际上是解析例程的繁重工作(在文件复制和windows排序之后),用Stringbuilder替换它取得了巨大的改进,总处理时间从20分钟降到了20分钟(复制+排序+解析)到5分钟的复制+排序和2分钟的解析,总共7分钟。速度提高130%如果删除写入硬盘的代码,速度有多快? 很多的减速都是因为硬盘驱动器的原因 因为你经常循环,我会把代码限制在循环内。删除重复的代码,在循环外获得尽可能多的代码 第一个if不需要,因为您已在while中检查null 如果您有很多类似的行,那么可能不需要一直拆分。您可以使用.StartsWith 如果文件是一致的,则不需要删除“.”,您可以与进行比较 因为你是在第二个if中检查一个空的tempstring。也许你想在分割之前这样做,因为分割一个空字符串是没有用的
您为获取新文件名所做的许多字符串操作都可以在循环之外完成。这似乎有点帮助,我的处理时间似乎提高了5%左右,我仍然怀疑我的瓶颈与磁盘IO有关,您对打开/写入文件的逻辑、缓冲区大小等有何建议?@weston Th使IO更快的唯一方法是限制读/写次数并限制指针的移动(例如:读/写大量不同的文件将使指针移动,而不仅仅是写入或读取一个文件)。或升级到更快的硬件。StringBuilder再次出现。我想知道,尝试调试使用字符串编写的程序所浪费的时间是否减少了字符串插入所节省的总内存。