【问题标题】:How can I efficiently index a file?如何有效地索引文件?
【发布时间】:2016-08-03 19:38:20
【问题描述】:

我正在处理一个需要从一系列可能较大的文本文件 (~3+ GB) 中随机读取整行文本的应用程序。

线条可以有不同的长度。

为了减少GC 并创建不必要的字符串,我使用Is there a better way to determine the number of lines in a large txt file(1-2 GB)? 提供的解决方案来检测每个新行并将其存储在一个映射中,因此产生lineNo => positionie 的索引:

// maps each line to it's corresponding fileStream.position in the file    
List<int> _lineNumberToFileStreamPositionMapping = new List<int>();
  1. 浏览整个文件
  2. 当检测到new line 增量lineCount 并将fileStream.Position 添加到_lineNumberToFileStreamPositionMapping

然后我们使用类似于以下的 API:

public void ReadLine(int lineNumber)
{
     var getStreamPosition = _lineNumberToFileStreamPositionMapping[lineNumber];
     //... set the stream position, read the byte array, convert to string etc.
}

此解决方案目前提供了良好的性能,但有两点我不喜欢:

  1. 由于我不知道文件中的总行数,我无法预先分配array,因此我必须使用List&lt;int&gt;,这可能会导致将大小调整为我实际需要的两倍;李>
  2. 内存使用情况,例如,对于具有约 500 万行文本的约 1GB 文本文件,索引占用约 150MB,我真的希望尽可能减少这一点。

非常感谢任何想法。

【问题讨论】:

  • 为什么索引是150gb? 500 万个整数不足 20mb 的原始存储空间,那么您从哪里获得这个价值?
  • 这就是分析器向我展示的内容,但我又没有深入挖掘。除此之外,20mb 将是理想的场景,但实际上由于 List 的调整大小逻辑,它可能是它的两倍
  • 也许你应该使用一个普通的旧数组。不确定Listactually 是否在这里为您提供任何有用的信息。建立列表后,将其转换为数组并以列表方式抛出。
  • 问题是文件在我阅读它们时确实会增长,所以List 允许我将新的附加行添加到索引中。
  • 啊,我明白了。好吧,您仍然可以将数组与Array.Resize(ref yourArray, newSize) 一起使用。您将必须自己完成工作,以确定这样做的工作是否值得从阵列中获得的速度提升。我有限的测试表明数组的速度将是原来的两倍。

标签: c# .net indexing filestream


【解决方案1】:
  1. 使用List.Capacity手动增加容量,可能每1000行左右。

  2. 如果您想用性能换取内存,您可以这样做:不要存储每条线的头寸,而只存储每 100 条(或其他)线的头寸。然后,比如说,需要第 253 行时,转到第 200 行的位置并向前数 53 行。

【讨论】:

  • aaaah...非常好!我很喜欢这个会试一试。 tnx!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-05
  • 2014-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-26
  • 2011-03-04
相关资源
最近更新 更多