如何使用多个异步或缓冲的IO流?

时间:2018-06-22 06:51:16

标签: c# iostream

我目前正在开发一个程序,该程序将大量数据(〜100mb)写入.txt文件。我在Google上搜索了如何优化不同的IO-Streams,但并没有真正理解以下内容:

  1. 如何一次打开多个流
  2. 如果默认情况下缓冲流,或者我必须使用BufferedStream
  3. 异步流和缓冲流之间的区别是什么

这是我的输出的当前状态:

for (int Row = 0; Row < RowCount; Row++)
{                   
    using (System.IO.StreamWriter file =
        new System.IO.StreamWriter(@"C:\Calculations\data1.txt", true))
            {
                file.WriteLine(Time + "\t" + Row + "\t" + Value1[Row]);
            }
    using (System.IO.StreamWriter file =
        new System.IO.StreamWriter(@"C:\Calculations\data2.txt", true))
            {
                file.WriteLine(Time + "\t" + tRow + "\t" + Value2[Row]);
            }
}

我认为这是做什么的

  • 打开流到data1.txt
  • 写入data1.txt
  • 关闭并刷新流
  • 打开流到data2.txt
  • 写入data2.txt
  • 关闭并刷新流

如果我是正确的话,那将是很多打开,关闭和刷新100mb数据的工作。我很想在一开始就打开多个流,在计算数据时写入所有数据,然后关闭并刷新流。

2 个答案:

答案 0 :(得分:3)

您的问题很多

一些随机点没有特定顺序

  1. 所有流在.net中都有一个内部缓冲区
  2. 没有,您不必缓冲它们,但是出于性能原因,您可以调整内部缓冲区的大小(这取决于很多因素)
  3. 异步IO是一个非常复杂的主题,在这里Asynchronous File I/O开始阅读

更多。

由于流处理了缓冲,因此您不必担心它,它将在需要时刷新(根据默认值或设置缓冲区的方式)。您无需关闭文件即可刷新。再一次,让流来处理它,或者,如果您愿意,可以使用“冲洗”来冲洗自己。

100mb对于现代SSD驱动器来说并不多,它可以在几毫秒内完成。再一次,如果不需要,则无需打开和关闭它。但是,要说的是,打开和关闭文件的开销很小,因此将访问权包装在using语句中并在平时进行读写操作有时是有益的/容易的

最后,是的,您可以打开多个流,但是它们不是线程安全的。这意味着,由于它们只有1个内部缓冲区,因此您必须使用锁,或者打开和关闭文件以确保其完整性。这并不是说多个线程无法写入文件,而是说它并不像它应该的那么琐碎。

如果您希望打开文件以进行同步读写,请不要忘记在完成操作后将其关闭/处理

祝你好运

答案 1 :(得分:1)

经过更多研究,我找到了第一个问题的解决方案。您可以像这样打开多个IO流:

StreamWriter file1 = File.CreateText(@"C:\Outputtests\OutputTest1.txt");
StreamWriter file2 = File.CreateText(@"C:\Outputtests\OutputTest2.txt");

像这样,您需要自己冲洗并关闭流。

我比较了运行时间,它为我的硬盘节省了约10000倍:

static void Main(string[] args)
{
    Stopwatch sw1 = new Stopwatch();
    Stopwatch sw2 = new Stopwatch();
    Stopwatch sw3 = new Stopwatch();

    sw1.Start();                            //first version: opens and closes file each time -> takes around 1 minute total
    for (int i = 0; i < 10000; i++)
    {
        using (System.IO.StreamWriter file1 =
            new System.IO.StreamWriter(@"C:\Outputtests\OutputTest1.txt", true))
        {
            file1.WriteLine(i);
        }
    }
    sw1.Stop();

    sw2.Start();                            //second version: flushes each time -> takes around 50ms
    StreamWriter file2 = File.CreateText(@"C:\Outputtests\OutputTest2.txt");
    for (int i = 0; i < 10000; i++)
    {
        file2.WriteLine(i);
        file2.Flush();
    }
    file2.Close();
    sw2.Stop();

    sw3.Start();                            //third version: flushes at the end -> takes around 10ms
    StreamWriter file3 = File.CreateText(@"C:\Outputtests\OutputTest3.txt");
    for (int i = 0; i < 10000; i++)
    {
        file3.WriteLine(i);
    }
    file3.Flush();
    file3.Close();
    sw3.Stop();

    Console.WriteLine("Output 1:\t" + sw1.ElapsedMilliseconds.ToString() + Environment.NewLine + "Output 2:\t" + sw2.ElapsedMilliseconds.ToString() + Environment.NewLine + "Output 3:\t" + sw3.ElapsedMilliseconds.ToString());
    Console.ReadKey();
}

不确定是否应该在IO-Stream中存储多少,直到必须将其冲洗掉。