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

时间:2014-12-30 07:56:14

标签: c# streamwriter writetofile

专家的一些帮助。我试图使用下面的函数将字符串打印到文件中。当我使用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:

大家好,感谢所有的帮助,你是最好的!!!根据您的所有建议和示例,我在外面定义了StreamWriter PrintFunction和这次只调用一次编写器进程,输出文件保持打开状态直到结束并以这种方式 打印过程速度与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
}

2 个答案:

答案 0 :(得分:4)

我对此进行了描述,看起来完全相反。我能够将.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;
        }
    }
}

答案 1 :(得分:1)

  

当我使用StreamWriter而不是Console.WriteLine()时,为什么打印速度会降低太多?

当您将命令输出重定向到文件时,无论您使用console.Write()

调用PrintFunction()多少次,cmd.exe都会立即获取输出文件的只写访问权限。

如果在PrintFunction()中使用流编写器,则每次都初始化编写器,尝试访问该文件,写入一行然后释放文件句柄。开销会影响性能。

  

我应该使用什么方法写入保持与Console.WriteLine()速度相同的文件?

您可以尝试以下其中一项

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