【发布时间】:2015-09-17 13:01:16
【问题描述】:
我编写了一个 Winform 应用程序,它读取文本文件的每一行,在该行上使用 RegEx 进行搜索和替换,然后写回一个新文件。我选择了“逐行”方法,因为有些文件太大而无法加载到内存中。
我正在使用 BackgroundWorker 对象,因此 UI 可以随着作业的进度而更新。下面是处理文件中行的读取和输出的代码(为简洁起见省略了部分)。
public void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Details of obtaining file paths omitted for brevity
int totalLineCount = File.ReadLines(inputFilePath).Count();
using (StreamReader sr = new StreamReader(inputFilePath))
{
int currentLine = 0;
String line;
while ((line = sr.ReadLine()) != null)
{
currentLine++;
// Match and replace contents of the line
// omitted for brevity
if (currentLine % 100 == 0)
{
int percentComplete = (currentLine * 100 / totalLineCount);
bgWorker.ReportProgress(percentComplete);
}
using (FileStream fs = new FileStream(outputFilePath, FileMode.Append, FileAccess.Write))
using (StreamWriter sw = new StreamWriter(fs))
{
sw.WriteLine(line);
}
}
}
}
我正在处理的一些文件非常大(8 GB,1.32 亿行)。该过程需要很长时间(完成一个 2 GB 的文件大约需要 9 小时)。它看起来以大约 58 KB/秒的速度工作。这是预期的还是应该加快进程?
【问题讨论】:
-
StreamWriter在追加一行时不会从头开始写入文件吗?如果每 1.32 亿行重新开始,可以解释为什么要花这么长时间。所以应该是132! (阶乘)操作 -
您可以逐行编写文件,而无需重新打开它并为每一行寻找结尾,你知道...只需在循环开始时打开输出文件一次。
-
决心等待 9 小时直到申请完成,然后再重新考虑您当前的流程哈哈
-
顺便说一下,根据你的Visual Studio版本,你可以使用Profiler来识别瓶颈msdn.microsoft.com/en-us/library/ms182372.aspx
-
@user1 是的,如果您将一行附加到现有文件,而不是重写,您最终会产生几种形式的开销。 1)对象的实例化 2)读取以找到结束指针等
标签: c# streamreader streamwriter