如何在不读取文件到结尾的情况下获取行数?

15

有没有一种方法可以获取大文本文件中的行数,但不需要读取文件内容或读取到文件结尾并进行计数++。

也许有一些文件属性,但根本找不到它。 因为在某些情况下,我可能需要获取总行数并将其与当前行进行比较,以显示百分比,仅仅为了显示百分比就先读取所有内容,然后再读取一遍以显示原始文本对用户来说可能是愚蠢的。

最好的


如果您控制文件格式,可以将行数作为元数据注入到外部文件或文件头中。您也可以逐个字符地阅读并检查换行符。但这种方法速度不会很快。 - Travis
正如大家已经说过的那样,一个可行的选项是向文件中添加自己的头。我为我的游戏实现了自定义Wavefront模型,就是这么做的。基本上,我有一个工具来优化.obj文件,摆脱我不需要的垃圾,然后在第一行写下总行数、面数、法线、顶点和纹理UV的数量。当加载模型时,各种数组缓冲区使用这些数据。 - Krythic
3个回答

22

不行,你必须读取文件。如果你想快速找到它而不用计算,可以考虑将其存储在文件的开头或另一个文件中。

请注意,你可以流式传输文件,速度非常快:

int count = File.ReadLines(path).Count();
因为有些情况下我需要获取总行数并将其与当前行进行比较,以显示百分比。但仅为了显示百分比,先读取所有内容再重新读取以显示原始文本可能是不太明智的。
哦,只需获取文件大小和每行的字节数,并累加已处理的字节数即可。

2
我认为这会导致内存问题,因为我要处理来自另一个应用程序生成的大于8GB的文件<>. - Rosmarine Popcorn
1
@Cody:File.ReadLines 方法不会一次性读取整个文件,因此它不会占用太多内存。但是该方法仅适用于 Framework 4 或更高版本。 - Guffa
1
@Cody:你可能想要尝试一下。File.ReadLines 返回一个 IEnumerable<string> - 它不会一次性将整个文件读入内存。 - John Saunders
@Cody:不,正如我所提到的,它会流式传输文件。它不会将整个文件读入内存。http://msdn.microsoft.com/en-us/library/dd383503.aspx - jason
2
@UrbanEsc:不,它仍然会流式传输文件。这是一个循环,基本上看起来像 int count = 0; using(var e = source.GetEnumerator()) { while(e.MoveNext()) { count++; } } return count;var = source.GetEnumerator()e.MoveNext() 基本上打开文件作为 StreamReader,然后重复执行 StreamReader.ReadLine。没有对文件进行缓冲。 - jason
显示剩余4条评论

13

不,没有其他方法。

文件不是基于行的(甚至不是基于字符的),因此没有关于行数(或字符数)的元信息。有关内容的唯一元数据是以字节为单位的长度。

如果您对文件有一些额外的信息,例如每行都是完全相同的长度,并且使用8位编码,使得字符数与字节数相同,那么您可以从文件大小计算出行数。


+1...并且需要定义好行尾序列,例如\r\n\n - D'Arcy Rittich
@Guffa,你能否告诉FileZilla:P - 开玩笑的,我正在处理FileZilla日志文件,它们非常大,所以我认为我不会显示百分比。 - Rosmarine Popcorn
@Cody: 你可以使用估计的平均行长度来得到近似的百分比,或者根据文件位置而不是行数来计算百分比。 - Guffa

5
如Guffa和Jason所说,除非读到结束,否则没有其他获取行的方法。 以不同的方式解决您的问题: 如果您只对百分比显示感兴趣,您可以尝试从总文件大小和当前所在行的行数累计该值。您需要在那里应用一些神秘技巧来获取实际读取的字节数(例如,假设您已经读取了前10行,共200个字节或任何其他内容),而文件大小为400个字节。您可能可以猜测您已经完成了50%,而无需知道总行数。
顺便说一下,这只是一些随机数字。

如果你只需要百分比而不是总行数,我认为这完全可行。 - user604613

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接