【问题标题】:Efficient way to parse large text file and work with data in it解析大型文本文件并处理其中数据的有效方法
【发布时间】:2016-06-28 11:18:03
【问题描述】:

每个人。 我想解析 300+Mb 文本文件,其中包含 2.000.000+ 行,并使用存储的数据进行一些操作(分割每一行,进行比较,将数据保存在字典中。)。 程序大约需要 50+ 分钟才能获得预期的结果(对于 80.000 行的文件,大约需要 15-20 秒) 有没有办法让它更快地工作? 下面的代码示例:

using (FileStream cut_file = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            using (BufferedStream bs = new BufferedStream(cut_file))
            using (StreamReader s_reader = new StreamReader(bs)) {
            string line;
                while ((line = s_reader.ReadLine()) != null) {
                    string[] every_item = line.Split('|'); //line sample: jdsga237 | 3332, 3223, 121 |
                    string car = every_item[0];
                    string[] cameras = every_item[1].Split(',');
                    if (!cars.Contains(car)) { //cars is List<string> defined at the beginning of programm
                        for (int camera = 0; camera < cameras.Count(); camera++) {
                            if (cams_input.Contains(cameras[camera])) { //cams_input is List<string> defined at the beginning of programm
                                cars.Add(car); 
                                result[myfile]++; //result is Dictionary<string, int>. Used dict. for parsing several files.
                            }
                        }
                    }
                }
            }

【问题讨论】:

  • 我认为您有内存问题。在程序运行时打开任务管理器并观察内存使用情况。如果您的计算机上没有足够的内存,则数据将被放入硬盘驱动器上的交换空间,这将显着降低应用程序的速度。尝试在内存更大的计算机上运行。
  • 两种解决方案:您可以尝试异步编写,否则不要逐行读取,尝试通过正则表达式解决。
  • 您还应该考虑一次性解析,因为 String.Split 在基本相同的字符串上多次使用时效率非常低。此外,您可以将HashSet&lt;String&gt; 用于cams_inputcars

标签: c# parsing text-files


【解决方案1】:

嗯,很有可能您遇到了与内存使用有关的问题。 但是,您在无用的 Linq 使用中存在一些明显的低效率: 当你在 List 上调用 Contains() 时,你基本上是在 List 上做一个 foreach。

因此,对您的代码的改进是使用 HashSet 而不是 List 以加快 Contains() 的速度。

在 for 循环中对数组调用 Count() 也是如此。它是一个数组,所以只需调用 Array.Length。

无论如何,您应该分析您机器中的代码(我使用 JetBrains Profiler 并发现执行这种性能分析非常宝贵)。

我对此的看法:

        string myfile = "";
        var cars = new HashSet<string>();
        var cams_input = new HashSet<string>();
        var result = new Dictionary<string, int>();
        foreach (var line in System.IO.File.ReadLines(myfile, System.Text.Encoding.UTF8))
        {
            var everyItem = line.Split('|'); //line sample: jdsga237 | 3332, 3223, 121 |
            var car = everyItem[0];
            if (cars.Contains(car)) continue;

            var cameras = everyItem[1].Split(',');

            for (int camera = 0; camera < cameras.Length; camera++)
            {
                if (cams_input.Contains(cameras[camera]))
                {
                    cars.Add(car);
                    // I really don't get who is inserting value zero.
                    result[myfile]++;
                }
            }
        }

编辑:根据您的评论,性能似乎与列表的使用有关。您应该阅读有关 .Net 框架中可用集合的指南,如下所示:http://www.codethinked.com/an-overview-of-system_collections_generic 每一种类型都最适合一种类型的任务:例如,HashSet 旨在用于存储一组(doh!)唯一值,它给你的真正闪亮的壮举是 O(1) 包含操作. 您支付的是哈希的存储和计算。 你也失去了排序等。

字典基本上是一个哈希集,每个键都有一个值。

好好学习!

Ps:如果问题解决了,请关闭问题。

【讨论】:

  • 谢谢。现在它工作得更快了。我不知道 HashSet (我是 C# 初学者)。 HashSet 有哪些我应该知道的陷阱?
猜你喜欢
  • 2011-12-16
  • 1970-01-01
  • 1970-01-01
  • 2018-12-31
  • 2019-03-11
  • 2011-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多