减慢 StreamWriter 将字符串打印到 C# 文件中的替代/更快方法
本文关键字:方法 文件 StreamWriter 字符串 打印 减慢 | 更新日期: 2023-09-27 18:35:35
专家的一些帮助。我正在尝试使用以下函数将字符串打印到文件中。当我使用 Console.Write() 或 Console.WriteLine() 时,输出文件每秒增长 3MB 或 4MB,但是当我尝试以如下所示的方式使用 StreamWriter 或 File.AppendAllText 输出时,文件每秒仅增长 20KB 或 30KB。
为什么当我使用 StreamWriter 而不是 Console.WriteLine() 时打印速度下降太多?我应该使用什么方法来写入保持与 Console.WriteLine() 相同速度的文件?
public static void PrintFunction()
{
//using (StreamWriter writer = File.AppendText(@"C:'OuputFile.txt"))
using (StreamWriter writer = new StreamWriter(@"C:'OuputFile.txt", true))
{
//Console.Write("This is "); // Print speed is about 3MB-4MB per second
writer.Write("This is "); //Print decreases to 20KB-30KB per second
//File.AppendAllText(@"C:'OuputFile.txt", "This is "); Print decreases to 20KB-30KB per second
// SOME CODE
// SOME CODE
//Console.WriteLine("the first line"); // Print speed is about 3MB-4MB per second
writer.WriteLine("the first line"); // Print decreases to 20KB-30KB per second
//File.AppendAllText(@"C:'OuputFile.txt", "the first line"); // Print decreases to 20KB-30KB per second
}
}
更新:当我说我正在使用 Console.WriteLine() 时,我的意思是,我在代码中使用 Console.WriteLine(),但为了将这些打印保存在文件中,我像这样重定向输出:
MyProgram.exe inputfile > outputfile.txt
我知道内存和硬盘的区别,但是为什么当我使用Console.WriteLine()如上所述重定向输出(打印到硬盘)时,打印速度比使用StreamWriter快1000倍以上?
我尝试像下面这样增加缓冲区大小,但打印速度并没有提高。
using (StreamWriter writer = new StreamWriter(@"C:'OuputFile.txt", true, Encoding.UTF8, 65536))
更新 2:
大家好,谢谢大家的帮助,你们很严谨!!.按照您的所有建议和示例,我在外面定义了StreamWriterPrintFunction,这次只调用一次编写器进程,输出文件保持打开状态,直到最后,以这种方式打印处理速度与 Console.WrileLine() 相同。
我已经将作者作为函数的参数传递,如下所示,它可以工作。我已经测试过 4KB、64KB 和如下所示的默认值,更快的结果是当我设置明确使用的缓冲区 4096 字节时。该函数被调用略多于1000万次,输出文件为670 MB。
*StreamWriter(@"C:'OuputFile.txt", true, Encoding.UTF8, 4096) --> 660845.1181 ms --> 11.0140853 min
StreamWriter(@"C:'OuputFile.txt", true, Encoding.UTF8, 65536) --> 675755.0119 ms --> 11.2625835 min
StreamWriter(@"C:'OuputFile.txt") --> 712830.3706 ms --> 11.8805061 min*
再次感谢您的帮助。
问候
代码如下所示:
public static void ProcessFunction()
{
StreamWriter writer = new StreamWriter(@"C:'OuputFile.txt", true, Encoding.UTF8, 4096);
while ( condition)
{
PrintFunction(writer);
}
if( writer != null )
{
writer.Dispose();
writer.Close();
}
}
public static void PrintFunction(StreamWriter writer)
{
//SOME CODE
writer.Write("Some string...");
//SOME CODE
}
我对此进行了分析,看起来完全相反。我能够将大约 .25GB/s 写入标准的 10K rpm 驱动器(无 SSD)。看起来您经常调用此函数,并通过每次都连接到文件来写入文件。尝试这样的事情(我从一段旧的控制台日志记录代码中快速将其截断在一起,因此它可能有点错误,并且错误处理肯定不完整):
public static class LogWriter
{
// we keep a static reference to the StreamWriter so the stream stays open
// this could be closed when not needed, but each open() takes resources
private static StreamWriter writer = null;
private static string LogFilePath = null;
public static void Init(string FilePath)
{
LogFilePath = FilePath;
}
public static void WriteLine(string LogText)
{
// create a writer if one does not exist
if(writer==null)
{
writer = new StreamWriter(File.Open(LogFilePath,FileMode.OpenOrCreate,FileAccess.Write,FileShare.ReadWrite));
}
try
{
// do the actual work
writer.WriteLine(LogText);
}
catch (Exception ex)
{
// very simplified exception logic... Might want to expand this
if(writer!=null)
{
writer.Dispose();
}
}
}
// Make sure you call this before you end
public static void Close()
{
if(writer!=null)
{
writer.Dispose();
writer = null;
}
}
}
为什么当我使用 StreamWriter 而不是 Console.WriteLine() 时打印速度下降太多?
当您将命令输出重定向到文件时,无论您使用控制台调用 PrintFunction() 多少次,cmd 都会立即获取输出文件的只写访问权限.exe一次。写()
如果在 PrintFunction() 中使用流编写器,则每次都初始化编写器,尝试访问文件,编写一行,然后释放文件句柄。开销会扼杀性能。
我应该使用什么方法来写入保持与 Console.WriteLine() 相同速度的文件?
您可以尝试以下方法之一
- 将所有
- 输出缓冲在内存中(例如使用StringBuilder),然后立即写入文件
- 将 StreamWriter 对象传递给 PrintFunction() 以避免开销。在最后正确处理 StreamWriter.Close()