在非常大的文件C#的所有行上循环[重复]

Posted

技术标签:

【中文标题】在非常大的文件C#的所有行上循环[重复]【英文标题】:Loop on all lines of very large file C# [duplicate] 【发布时间】:2018-08-15 09:40:13 【问题描述】:

我想使用foreach循环一个非常大的文件(例如 10GB)的所有行

我目前正在像这样使用File.ReadLines

var lines = File.ReadLines(fileName);
foreach (var line in lines) 
  // Process line

但是如果文件大于 2MB,这会很慢,而且循环会很慢。

如何循环播放非常大的文件?

任何帮助将不胜感激。

谢谢!

【问题讨论】:

What's the fastest way to read a text file line-by-line?的可能重复 【参考方案1】:

考虑到这一点,你做的方式是最好的方式

您不想一次将整个文件读入 RAM 您的行处理独立于之前的行

抱歉,从硬盘读取内容很慢。

改进可能来自其他来源:

将文件存储在速度更快的设备(SSD?)上 获取更多 RAM 以将文件读入内存以至少加快处理速度

【讨论】:

【参考方案2】:

首先你需要读取整个文件还是只读取文件的一部分。

如果你只需要阅读文件的部分

const int chunkSize = 1024; // read the file by chunks of 1KB
using (var file = File.OpenRead("yourfile"))

    int bytesRead;
    var buffer = new byte[chunkSize];
    while ((bytesRead = file.Read(buffer, 0 /* start offset */, buffer.Length)) > 0)
    
        // TODO: Process bytesRead number of bytes from the buffer
        // not the entire buffer as the size of the buffer is 1KB
        // whereas the actual number of bytes that are read are 
        // stored in the bytesRead integer.
    

如果需要将整个文件加载到内存中。

重复使用此方法,而不是直接加载到内存中,因为您可以控制自己在做什么,并且可以随时停止该过程。

或者你可以使用MemoryMappedFile https://msdn.microsoft.com/en-us/library/system.io.memorymappedfiles.memorymappedfile.aspx?f=255&MSPPError=-2147217396

内存映射文件会给程序一个从内存访问的视图,但它只会第一次从磁盘加载。

long offset = 0x10000000; // 256 megabytes
long length = 0x20000000; // 512 megabytes

// Create the memory-mapped file.
using (var mmf = MemoryMappedFile.CreateFromFile(@"c:\ExtremelyLargeImage.data", FileMode.Open,"ImgA"))

     // Create a random access view, from the 256th megabyte (the offset)
     // to the 768th megabyte (the offset plus length).
     using (var accessor = mmf.CreateViewAccessor(offset, length))
     
         //Your process
     

【讨论】:

为什么你认为 OP 只需要文件的一部分? 我打赌 OP 正在逐行读取和处理:\ 您的编辑忽略了 File.ReadLines 为您完成所有这些流式传输的事实。 我仍然相信这种方法甚至可以将整个文件加载到内存中更好,因为您可以控制该过程并在需要时适当地显示消息 我不明白这如何适用于这个问题。当然你可以这样做......并在此基础上编写大量代码甚至达到 OP 认为的给定......但这仍然没有提高速度。【参考方案3】:

由于您必须循环的项目数量众多,因此循环总是很慢。我很确定这不是循环,而是您在每一条减慢它的行上所做的实际工作。一个有 10GB 行的文件实际上可能有数万亿行,除了最简单的任务之外的任何事情都需要很多时间。

您总是可以尝试使作业线程化,以便不同的线程在不同的行上工作。这样至少你有更多的核心来解决这个问题。

设置一个 for 循环并让它们以不同的量递增。

另外,我不是 100%,但我认为你可以通过根据新行拆分将整个内容拆分为字符串数组,然后处理这些内容,因为所有内容都存储在内存中,因此速度会大大提高。

string lines = "your huge text";
string[] words = lines.Split('\n');
foreach(string singleLine in lines)



** 基于 cmets 添加 ** 所以有很大的缺点,并且会占用大量的内存。至少原始文件使用的数量,但这解决了硬盘驱动器速度慢的问题,所有数据将直接读取到机器的 RAM 中,这将远远快于从硬盘驱动器中读取小块.

这里还有一个问题是大约 20 亿行的限制,因为这是您可以拥有的数组中的最大条目数。

【讨论】:

所以...手动将 10GB 数据复制到代码中,从而产生 10GB 的内存字符串文字?听起来很有趣…… 你在猜吗?因为我认为你根本没有测试过这个。它不仅可能会更慢,还会浪费大约 20 GB 或更多的 RAM。 "10GB 行的文件实际上会有数万亿行..." -> 粘贴到数组。所以现在我们有一个 10gb 的字符串文字(编译器将如何处理它(实际上我很好奇)),现在我们有一个包含 10gb 条目的数组(我也很好奇它将如何处理)。 这里的cmets:“你在猜吗?因为我认为你根本没有测试过这个”。当然我没有测试过这个。我没有得到报酬。这些只是我的想法。 OP 可以到处玩,看看什么是最快的 我同意,从 RAM 读取比从 HDD 读取“快得多”,但是您的解决方案需要以慢速 HDD 的速度从慢速 HDD 读取到快速 RAM。这不是和我从硬盘中逐行读取文件一样吗?

以上是关于在非常大的文件C#的所有行上循环[重复]的主要内容,如果未能解决你的问题,请参考以下文章

在数据框的所有行上应用函数[重复]

在 libtool 命令行上重复库

对 C# 循环中的多线程感到困惑 [重复]

有效地读取 R 中的一个非常大的文本文件 [重复]

重命名非常大的 CSV 数据文件的列 [重复]

正则表达式在非常大的html文件中匹配java中的花括号[重复]