减慢 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
}

减慢 StreamWriter 将字符串打印到 C# 文件中的替代/更快方法

我对此进行了分析,看起来完全相反。我能够将大约 .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() 相同速度的文件?

您可以尝试以下方法之一

    将所有
  1. 输出缓冲在内存中(例如使用StringBuilder),然后立即写入文件
  2. 将 StreamWriter 对象传递给 PrintFunction() 以避免开销。在最后正确处理 StreamWriter.Close()