如何高效地用C#编写大型文本文件?
我正在用C#创建一个方法,为一个文件生成一个文本文件。提要将包含30000条以上的记录,文本文件目前的重量约为7Mb 以下是我当前使用的代码(为了简洁起见,删除了一些行) 我想知道StringBuilder是否适合这项工作。如果我改用TextWriter,性能会有所提高吗如何高效地用C#编写大型文本文件?,c#,text-files,io,C#,Text Files,Io,我正在用C#创建一个方法,为一个文件生成一个文本文件。提要将包含30000条以上的记录,文本文件目前的重量约为7Mb 以下是我当前使用的代码(为了简洁起见,删除了一些行) 我想知道StringBuilder是否适合这项工作。如果我改用TextWriter,性能会有所提高吗 我对IO性能一窍不通,因此如有任何帮助或总体改进,将不胜感激。谢谢。使用StreamWriter一次编写一个字符串。编写而不是在StringBuilder中缓存所有内容。只需使用语句移动,使其包含整个代码,然后直接写入文件。我
我对IO性能一窍不通,因此如有任何帮助或总体改进,将不胜感激。谢谢。使用StreamWriter一次编写一个字符串。编写而不是在StringBuilder中缓存所有内容。只需使用
语句移动,使其包含整个代码,然后直接写入文件。我认为没有必要先把它全部保存在内存中。文件I/O操作在现代操作系统中通常得到了很好的优化。您不应该尝试将文件的整个字符串组合到内存中。。。把它一件一件地写出来。FileStream
将考虑缓冲和其他性能因素
您可以通过移动以下内容轻松进行此更改:
using (StreamWriter outfile = new StreamWriter(filePath)) {
到函数的顶部,并摆脱直接写入文件的StringBuilder
避免在内存中建立大字符串有几个原因:
实际上,它的性能可能更差,因为StringBuilder
必须在写入时增加其容量,从而导致内存的重新分配和复制
它可能需要比物理分配更多的内存,这可能导致使用比RAM慢得多的虚拟内存(交换文件)
对于真正大的文件(>2Gb),您将耗尽地址空间(在32位平台上),并且永远无法完成
要将StringBuilder
内容写入文件,必须使用ToString()
,因为两个副本都必须在内存中保存一段时间,因此这会有效地将进程的内存消耗增加一倍。如果您的地址空间足够零碎,导致无法分配单个连续内存块,则此操作也可能失败
这可能很旧,但我有一个文件要写,大约1700万行
因此,我最终每10k行批处理一次写操作,类似于这些行
for (i6 = 1; i6 <= ball; i6++)
{ //this is middle of 6 deep nest ..
counter++;
// modus to get a value at every so often 10k lines
divtrue = counter % 10000; // remainder operator % for 10k
// build the string of fields with \n at the end
lineout = lineout + whatever
// the magic 10k block here
if (divtrue.Equals(0))
{
using (StreamWriter outFile = new StreamWriter(@filepath, true))
{
// write the 10k lines with .write NOT writeline..
outFile.Write(lineout);
}
// reset the string so we dont do silly like memory overflow
lineout = "";
}
}
用于(i6=1;i6我真的希望你不是想让他一次写一点。虽然这是一个很好的答案。我有一个大约20Mb大小的文件,我面临的问题是StreamWriter实际上在末尾放了一个回车符/新行。我正试图在最后删除多余的回车符,正如已经指出的那样StringBuilder在性能和大小方面都不是一个很好的解决方案。我尝试了StreamReader.Peek()在它结束之前查看这一行。有什么想法吗?@MaximusMeters您可能在这期间找到了自己的方法,但可能您使用的是WriteLine()
方法而不是Write()
?回答很好。可以使用StreamWriter构造函数重载来尝试调整,该重载允许您定义缓冲区大小…嘿,感谢您的回答!我感谢您花时间添加关于如何处理此类场景的进一步解释。5年后,FileStream
类仍然是编写tex的最佳方法吗t文件~7MB?自从我写这个问题以来,Linq2Csv项目就开始了。这是处理我正在写的代码的一种更好的方式。有没有完整的源代码和解决方案?对不起,它是为我的一个客户写的。你真的应该看看Linq2Csv。它将使这类事情变得更容易。自从我上次对t的评论以来已经将近5年了对于他的问题,我强烈推荐CsvHelper。
for (i6 = 1; i6 <= ball; i6++)
{ //this is middle of 6 deep nest ..
counter++;
// modus to get a value at every so often 10k lines
divtrue = counter % 10000; // remainder operator % for 10k
// build the string of fields with \n at the end
lineout = lineout + whatever
// the magic 10k block here
if (divtrue.Equals(0))
{
using (StreamWriter outFile = new StreamWriter(@filepath, true))
{
// write the 10k lines with .write NOT writeline..
outFile.Write(lineout);
}
// reset the string so we dont do silly like memory overflow
lineout = "";
}
}