【发布时间】: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>();
- 浏览整个文件
- 当检测到
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.
}
此解决方案目前提供了良好的性能,但有两点我不喜欢:
- 由于我不知道文件中的总行数,我无法预先分配
array,因此我必须使用List<int>,这可能会导致将大小调整为我实际需要的两倍;李> - 内存使用情况,例如,对于具有约 500 万行文本的约 1GB 文本文件,索引占用约 150MB,我真的希望尽可能减少这一点。
非常感谢任何想法。
【问题讨论】:
-
为什么索引是150gb? 500 万个整数不足 20mb 的原始存储空间,那么您从哪里获得这个价值?
-
这就是分析器向我展示的内容,但我又没有深入挖掘。除此之外,20mb 将是理想的场景,但实际上由于
List的调整大小逻辑,它可能是它的两倍 -
也许你应该使用一个普通的旧数组。不确定
Listactually 是否在这里为您提供任何有用的信息。建立列表后,将其转换为数组并以列表方式抛出。 -
问题是文件在我阅读它们时确实会增长,所以
List允许我将新的附加行添加到索引中。 -
啊,我明白了。好吧,您仍然可以将数组与
Array.Resize(ref yourArray, newSize)一起使用。您将必须自己完成工作,以确定这样做的工作是否值得从阵列中获得的速度提升。我有限的测试表明数组的速度将是原来的两倍。
标签: c# .net indexing filestream