c# - 读取非常大的文本文件,我应该合并异步吗?

标签 c# asynchronous streamreader

我一直面临着产生一种方法的挑战,该方法将非常大的文本文件读入程序,这些文件的范围从 2gb 到 100gb。

目前的想法是将大约 1000 行文本读入该方法。

目前程序是使用流读取器逐行读取文件并处理在该行找到的必要数据区域设置的。

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 对我不起作用,因为我会遇到这些内存错误。

最后,我一直在研究异步,作为一种创建方法的方法,该方法将读取一定数量的行并在处理下一批行之前等待调用。

这让我想到了我的问题,我正在努力理解异步,而且我似乎找不到任何可以帮助我学习的 Material ,希望这里有人可以帮助我理解异步。

当然,如果有人知道解决这个问题的更好方法,我会洗耳恭听。

编辑 添加了剩余的代码以结束任何混淆。

最佳答案

您的问题不在于同步 v 的异步,而是您正在读取整个文件并将文件的部分内容存储在您对数据执行某些操作之前.

如果您读取每一行,对其进行处理并将结果写入另一个文件/数据库,那么 StreamReader 将允许您处理多 GB(或 TB)的文件。

只有当你存储文件的一部分直到你读完它才会有问题,然后你会遇到内存问题(但你会惊讶于你可以让 Lists 有多大& Dictionaries 在内存不足之前获取)

您需要做的是尽快保存处理后的数据,而不是将其保存在内存中(或尽可能少地保存在内存中)。

对于大文件,您可能需要将您的工作集(您的处理数据)保存在数据库中 - 可能像 SqlExpress 或 SqlLite 这样的东西会做(但同样,这取决于您的工作集有多大)。

希望这会有所帮助,请不要犹豫,在评论中提出更多问题,或编辑您的原始问题,如果我能以任何方式提供帮助,我会更新此答案。

更新 - 分页/分块

您需要以一页为单位读取文本文件,并允许用户滚动文件中的“页面”。当用户滚动时,您会阅读并向他们展示下一页。

现在,您可以做一些事情来帮助自己,始终在内存中保留大约 10 个页面,这可以让您的应用在用户快速向上/向下翻几页时做出响应。在应用程序空闲时间(Application Idle event)你可以读取接下来的几页,你再次丢弃当前页面之前或之后超过五页的页面。

向后翻页是个问题,因为您不知道文件中每一行的开始或结束位置,因此您不知道每一页的开始或结束位置。因此,对于向后分页,当您向下阅读文件时,保留每页开头的偏移量列表(Stream.Pos),然后您可以快速Seek到给定位置并从那里读取页面。

如果您需要允许用户搜索文件,那么您几乎可以逐行阅读文件(边走边记住页面偏移量)以查找文本,然后当您找到内容时,读入并阅读向他们展示该页面。

您可以通过将文件预处理到数据库中来加快一切速度,网格控件可以处理动态数据集(它们会为您进行分页),并且您可以获得内置搜索/过滤器的好处。

因此,从某些的角度来看,这是异步读取文件,但这是从用户的角度来看。但是从技术的角度来看,当我们谈论在编程时做一些异步的事情时,我们往往指的是别的东西。

关于c# - 读取非常大的文本文件,我应该合并异步吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15954029/

相关文章:

vb.net 从 .txt 文件读取并显示内容

c# - 在读取文本文件时,它只读取其中的一部分

node.js - Firebase 查询快照未定义

c# - CoVariance 和 ContraVariance 中的类型安全

c# - 等到我的线程结束

c# - 使用 foDicom Dicom Anonymizer 和安全配置文件

c# - 未处理的异步异常

c# - 如何从PowerBuilder中的外部函数异步获取返回值的值?

VB.Net:按行搜索Word文档

c# - NLog Header(忽略布局)