在C#中高效地写入大文件列表

时间:2016-10-01 16:58:52

标签: c# .net multithreading file

我认为这是一个相当普遍的问题,但是我没有设法找到一个好的解决方案或浏览这个论坛。

问题

我编写了一个工具来获取文件夹的文件列表,其中包含一些其他信息,例如文件名,文件路径,文件大小,哈希等。

我遇到的最大问题是某些文件夹包含数百万个文件(结构中可能有5000万个文件)。

可能的解决方案

我有两个解决方案,但它们都不理想。

  1. 每次读取文件时,信息都会直接写入文件。这没关系,但这意味着我无法对文件进行多线程处理,而不会遇到锁定文件的线程问题。

  2. 每次读取文件时,信息都会添加到某种形式的集合中,例如ConcurrentBag。我可以多线程化文件的枚举并将它们添加到集合中。枚举完成后,我可以使用File.WriteAllLines将整个集合写入文件;但是,在集合中添加5000万个条目会使大多数机器内存不足。

  3. 其他选项

    是否有任何方法可以将项目添加到集合中,然后在它到达集合中的特定数量的记录时将其写入文件?或者类似的东西?

    我查看了一个BlockingCollection,但由于生产者将是多线程的,因此填充速度非常快,但消费者只能是单线程的。

2 个答案:

答案 0 :(得分:1)

创建一个由所有线程共享的FileStream。在写入该FileStream之前,线程必须将其锁定。 FileStream有一些缓冲区(如果我没记错的话,有4096字节),因此它实际上并不是每次都写入磁盘。如果4096字节还不够,你可以使用BufferedStream。

答案 1 :(得分:1)

BlockingCollection正是您所需要的。您可以创建一个具有大缓冲区的文件,并使用一个写入程序线程写入一个文件,该文件在运行期间保持打开状态。

如果读取是主导操作,则整个时间队列将接近空,总时间将略微超过读取时间。

如果写入是占主导地位的操作,则队列将填满,直到达到您设置的限制(以防止内存不足的情况),并且生产者只会在作者前进时前进。总时间将是按顺序将所有记录写入单个文件所需的时间,并且您不能做得更好(当编写器是最慢的部分时)。

您可以通过多个阻止集合进行流水线操作,从而获得更好的性能,例如:使哈希计算(CPU绑定操作)可能与读取或写入操作分开。如果您想这样做,请考虑TPL DataFlow库。