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



我目前正在开发一个将大量数据(~100mb(写入.txt文件的程序。我用谷歌搜索了一下如何优化不同的 IO 流,但并不真正了解以下内容:

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

这是我输出的当前状态:

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

我认为这是做什么的:

  • 打开流到数据1.txt
  • 写入数据1.txt
  • 关闭和刷新流
  • 打开流到数据2.txt
  • 写入数据2.txt
  • 关闭和刷新流

如果我是正确的,那将是大量打开、关闭和刷新 100mb 数据的过程。我很想在开始时打开多个流,在计算时写入所有数据,然后关闭并刷新流。

你的问题有很多

一些随机点没有特定的顺序

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

此外。

由于缓冲由流负责,因此您无需担心它,它会在需要时刷新它(根据默认值或您设置缓冲区的方式(。您无需关闭文件即可刷新。再一次,让流处理它,或者如果您愿意,可以使用"冲洗"自行冲洗它

对于现代SSD驱动器来说,100mb并不多,它可以在几毫秒内完成。再一次,如果您不需要,则无需打开和关闭它。然而,话虽如此,打开和关闭文件有开销,但它最小,所以有时将访问包装在一个using语句中并在和平餐的基础上读取和写入是有益的/明智的

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

如果要使文件保持打开状态以同步读取和写入,请在完成后不要忘记关闭/处理它们

祝你好运

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

StreamWriter file1 = File.CreateText(@"C:OutputtestsOutputTest1.txt");
StreamWriter file2 = File.CreateText(@"C:OutputtestsOutputTest2.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:OutputtestsOutputTest1.txt", true))
{
file1.WriteLine(i);
}
}
sw1.Stop();
sw2.Start();                            //second version: flushes each time -> takes around 50ms
StreamWriter file2 = File.CreateText(@"C:OutputtestsOutputTest2.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:OutputtestsOutputTest3.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 之前应该在 IO-Stream 中存储多少。