在非常大的文件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#的所有行上循环[重复]的主要内容,如果未能解决你的问题,请参考以下文章