我一直面临着制作一种方法的挑战,该方法将非常大的文本文件读入程序,这些文件的范围可以从2gb到100gb。
到目前为止,这个想法一直是在方法中读出几千行文字。
目前,使用流阅读器设置程序,逐行读取文件并处理在该行上找到的必要数据区域。
using (StreamReader reader = new StreamReader("FileName"))
{
string nextline = reader.ReadLine();
string textline = null;
while (nextline != null)
{
textline = nextline;
Row rw = new Row();
var property = from matchID in xmldata
from matching in matchID.MyProperty
where matchID.ID == textline.Substring(0, 3).TrimEnd()
select matching;
string IDD = textline.Substring(0, 3).TrimEnd();
foreach (var field in property)
{
Field fl = new Field();
fl.Name = field.name;
fl.Data = textline.Substring(field.startByte - 1, field.length).TrimEnd();
fl.Order = order;
fl.Show = true;
order++;
rw.ID = IDD;
rw.AddField(fl);
}
rec.Rows.Add(rw);
nextline = reader.ReadLine();
if ((nextline == null) || (NewPack == nextline.Substring(0, 3).TrimEnd()))
{
d.ID = IDs.ToString();
d.Records.Add(rec);
IDs++;
DataList.Add(d.ID, d);
rec = new Record();
d = new Data();
}
}
}
程序继续进行并填充一个类。 (刚决定不发布其余的)
我知道一旦程序显示一个非常大的文件,就会发生内存异常错误。
所以这是我当前的问题,到目前为止我一直在谷歌搜索几种方法,很多人只是回答使用流阅读器和reader.readtoend,我知道readtoend不会为我工作,因为我会得到那些内存错误。
最后,我一直在寻找异步作为一种创建方法的方法,该方法将读取一定数量的行并在处理下一行行之前等待调用。
这让我想到了我的问题,我正在努力理解异步,我似乎无法找到任何可以帮助我学习的材料,并且希望有人可以帮助我解决异步问题。
当然,如果有人知道一个更好的方法来解决这个问题,我很满意。
编辑添加了剩余的代码以结束任何混淆。
答案 0 :(得分:6)
您的问题不是同步v异步,而是您在使用该数据做某事之前,正在读取整个文件并存储部分文件在内存中
如果您正在阅读每一行,处理它并将结果写入另一个文件/数据库,那么StreamReader
将允许您处理多GB(或TB)文件。
如果您在完成阅读之前存储了部分文件,那么只会出现问题,那么您可能会遇到内存问题(但是您会惊讶地发现有多大文件可以让Lists
& { {1}}在你的内存耗尽之前得到)
您需要做的是尽快保存已处理的数据,而不是将其保留在内存中(或尽可能保留在内存中)。
对于文件很大,您可能需要将工作集(处理数据)保存在数据库中 - 可能像SqlExpress或SqlLite那样(但同样,它取决于工作集的大小)。
希望这有帮助,不要犹豫,在评论中提出进一步的问题,或编辑你的原始问题,如果我能以任何方式提供帮助,我会更新这个答案。
更新 - 分页/分块
您需要以一页的块读取文本文件,并允许用户滚动文件中的“页面”。当用户滚动时,您会阅读并在下一页显示它们。
现在,您可以做一些事情来帮助自己,始终在内存中保留大约10页,这样,如果用户非常快速地向上/向下翻页几页,您的应用就会响应。在应用程序空闲时间(应用程序空闲事件)中,您可以在接下来的几页中阅读,再次丢弃当前页面之前或之后超过五页的页面。
向后分页是一个问题,因为您不知道每行在文件中的开始或结束位置,因此您不知道每个页面的开始或结束位置。因此,对于向后翻页,当您通读文件时,请在每个页面的开头(Dictionaries
)保留一个偏移列表,然后您可以快速Stream.Pos
到指定位置并阅读从那里。
如果您需要允许用户搜索文件,那么您几乎可以逐行读取文件(记住页面偏移),查找文本,然后当您找到某些内容时,请阅读和向他们展示那页。
您可以通过将文件预处理到数据库来加速一切,有一些网格控件可以处理动态数据集(它们将为您进行分页),您可以获得内置搜索/过滤器的好处。
因此,从某些的角度来看,这是在异步读取文件 ,但这是从用户的角度来看。但是从技术角度来看,当我们谈论在编程时做异步时,我们往往会有别的意思。