【问题标题】:How to read last 10 line of text file using CStdioFile如何使用 CStdioFile 读取文本文件的最后 10 行
【发布时间】:2011-09-12 08:41:01
【问题描述】:

我想阅读一个大文本文件的最后 10 行。 通常我会遍历文件并获取最后 10 行。 请告诉我,还有其他方法可以更快地阅读最后几行。

谢谢。

【问题讨论】:

    标签: c++ mfc


    【解决方案1】:

    您可以使用 (CStdioFile::GetLength)(继承自 CFile)获取文件的字节长度:

    http://msdn.microsoft.com/en-US/library/b569d0t4(v=VS.80).aspx

    您可以使用CStdioFile::Seek 跳转到任意偏移量:

    http://msdn.microsoft.com/en-US/library/8c5ccz0x(v=VS.80).aspx

    如果行长是固定的,那么读取最后 N 行是一个非常简单的问题。但是没有“向后读取”操作,在一般情况下,您不知道任意文本文件中的行有多长。 (如果您想更快地执行此操作,您可以构建和维护一个跟踪它的索引文件。)

    请注意,一次查找和阅读一个字符可能效率低下。究竟如何效率低下取决于几个因素。尽管在操作系统级别进行缓冲可能不会像每次返回磁盘时那样糟糕,但每次查找和每次调用时总会有开销读操作。

    因此,您最好选择一个缓冲区大小,然后逐步读取块。强烈表明这是有用的,请参阅一些名为 tail 的 UNIX 源代码。它获取文件的最后 N 行,虽然它是用 C 编写的,但它可能会给您一些见解:

    http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/tail.c#n477

    【讨论】:

    • 非常感谢。我有固定长度的线。所以我可以找到我想要的行并开始阅读。 :)
    • 该方法的效率由操作系统的缓冲区缓存级别保证。我礼貌地请求您删除答案的那部分;很明显,您不喜欢这种方法,但没有理由在您的回答中提及它。请考虑通过对我的回答发表评论来更改它。
    • @Baltasarq:首先,搜索可以刷新缓冲区。这取决于操作系统的实现是否聪明。完全刷新并不是唯一可能导致效率低下的原因,因为函数调用开销和每次读取操作以检查是否应使用缓冲区也不是完全空闲的。
    • 我已经概括了我的回答,没有具体提及您,而是在对您的评论中指出了我的回答。更好?
    • 一次读取(相当大的)块的一个原因是,以正确的顺序而不是向后读取扇区通常更有效。一次向后读取一个扇区可能意味着磁盘在同一磁道上读取的每个扇区之间几乎旋转了一整圈,而不是每圈读取多个扇区。不过,这对于少量大小合理的行可能并不重要。
    【解决方案2】:

    在二进制文件中,您(通常)具有固定的记录长度。在文本文件中,一种可能性是将文本行视为划分文件内容的记录。不幸的是,常规文本文件中的行不是固定大小的,因此您不能依赖以下公式:

    lastTenthLine = ( LengthOfFile / LengthOfLine ) - 10;
    

    我能想到的唯一方法是将读取指针移动到文件末尾。 Tne 开始向后阅读,每次一个字符,并计算您通过 '\n' 字符的次数。数了十次后,就可以返回下一个字符位置了。

    (请注意,您可能会遇到“结束行问题”,具体取决于您作为示例使用的文件的来源(OS)。由于您使用的是 MFC,只要使用的文件是在 Windows 中生成的)

    由于我认为这是家庭作业,因此我不会发布代码。您在这里有关于 MFC 的文档,解释了如何处理文件。您需要 CFile::ReadCFile::Seek 方法(除了打开和关闭)。注意CFileCStdioClass的父类。

    http://msdn.microsoft.com/en-us/library/ey6xh9bk(v=vs.80).aspx

    希望这会有所帮助。

    【讨论】:

    • 我当然希望它不是家庭作业,因为这表明世界上有某个地方在教授使用 MFC 的课程! :-/
    • 一次查找/读取一个字符可能效率低下。看我的回答。很多 I/O 操作比看起来更复杂:hostilefork.com/2010/03/14/…
    • @Hostile Fork,感谢您接受我的请求。也感谢您指出整个问题。
    猜你喜欢
    • 1970-01-01
    • 2018-07-16
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    相关资源
    最近更新 更多