【问题标题】:C++ Read only random lines in a fileC++ 只读文件中的随机行
【发布时间】:2013-04-25 10:59:37
【问题描述】:

我需要读取文本文件,但它太大了,所以我决定只读取这个文件中的一些行。我可以使用 seek 方法来跳转给定的行吗?然后我只能读取该行,因为该文本文件太大,读取整个文件会浪费大量时间。如果不可能,有人会为此提供更好的解决方案吗? (寻找给定的行并读取它)(我知道二进制文本文件正在逐字节读取)

我的文件的前文件

event1 0

subevent 1

subevent 2

event2  3 

(在我的文件中,在一个事件之后,它会显示我想寻找前一个事件的行数)

【问题讨论】:

  • 你不能每句话都换行,这个概念不存在。您必须手动查找线路结束的位置。实现“线”概念的唯一方法是每条线都有固定的长度,否则你必须逐行获取并跳过你不想要的。
  • ...或通过在文件中添加行号。
  • @hansmaad:好主意 - 会很好,但如果你随机选择一个行号然后必须执行二进制或插值查找来找到它,与直接索引到随机位置相比,它仍然相当昂贵与行号无关,然后寻找上一行或下一行结尾......
  • @hansmaad,这如何帮助您寻找特定的“线路”?
  • @uberwulu:问题是文件大,解析慢;将如何增大解析速度并降低解析速度?

标签: c++ c++11 c++builder


【解决方案1】:

是的,您可以查找文件中的某个点,然后从那里读取。一个可能的问题是,如果行的长度都不同,则文件中的随机位置将有更高的概率位于较长的行中:您不会得到不同行的均匀分布概率。如果您真的必须具有相同的概率,那么您需要至少遍历文件以找到每一行的开头 - 然后您可以将这些偏移量存储在一个向量中并随机选择一个向量元素来指导寻找行数据在文件中。如果您只关心一点点,那么您也许可以将少量但随机的行数超过您最初寻求的行……这会增加一些可能性,避免最初的通过,但并不完美。 hansmaad 的评论也添加了一种简洁的方法 - 完美的结果和非常好的性能 - 但要求您在文件本身中对所有行进行编号。

【讨论】:

  • “你可以在文件中寻找一个点然后从那里读取”:如果文件是在文本模式下打开的,则不会。寻找任意点是未定义的行为。 (它通常在 Unix 下工作,并且会让你在 Windows 下附近的某个地方,但它可能会做一些完全随机的事情。)
  • @JamesKanze:有趣的一点——那么最好使用二进制模式。干杯。
  • @JamesKanze:Posix 没有定义文本和二进制模式是相同的吗?如果属实,则说明它通常在 Unix 下工作;-) 不过我不记得参考了,因此它们有可能在您看到的数据方面保证相同,但在搜索方面则不然。
  • @SteveJessop 我不确定它能保证多远,但在实践中,我认为你可以指望它们在 Unix 和类 Unix 系统下是相同的。 (文本和二进制之间的区别被引入 C 以支持非 Unix 系统。在 C 开始在非 Unix 系统上使用之前,它并不存在。)
【解决方案2】:

除非每一行的长度完全相同,否则您将不得不扫描它。

如果您想在其中跳转,可以扫描它,将每行的偏移量保存在您选择的容器中,然后使用它来寻找特定的行。

【讨论】:

    【解决方案3】:

    假设这些行是可变/随机长度的,我不相信有任何内置方法可以直接跳转到特定行的开头。您可以查找文件中的任意字节位置。但是,这可能会落在一行的开头/中间/结尾的任何位置。

    我最好的建议是分两步解决问题:

    首先,逐字节完整地遍历文件,搜索每一行的开头。记录每一行的字节位置并将其存储到数组、向量等中。(基本上,您正在创建一个从行号映射到起始位置的索引。)然后,当您建立了这个索引时,您可以轻松跳转通过查找索引中的位置,到特定的行。

    【讨论】:

    • 感谢您的所有回答,实际上您的第二个想法目前也在我的脑海中发挥作用,但是这个文件由引擎创建,如果创建后,我想快速完成这项任务,问题是它会占用大量时间,但我也认为他们没有其他方法可以做到这一点:(在考虑这种情况时,时间非常重要,因为时间会做出一些重要的决定:)
    【解决方案4】:

    据我所知,没有内置方法可以在不知道行在哪里的情况下寻找新行。我无法告诉您实现目标的最佳方式,因为您的大部分问题都详细说明了如何您正在尝试实现它,而不是什么 em> 这是你真正想要完成的。因此,我可能会采用以下两种方式之一:

    1) 如果您确实需要文件中的每一位数据(没有可以丢弃的元数据或其他信息):

    有人提到扫描文件,在执行过程中跟踪行并使用它建立索引,以便一次读取一行。这可能会奏效,如果您实际上需要完整的每一行,或者您只需要行号并计划从那里一次读取小块,这将是可行的方法。但是,在不了解您的约束或要求的详细信息的情况下,我不建议使用此方法阅读整行,原因有一个:我无法知道一行本身不会太大而无法加载(如果只有文件中的一行?)。

    相反,我会简单地分配一个大小合适的缓冲区,一次处理,并以该大小的块处理文件,直到你到达最后。您可以随时输入更多数据。如果没有其他详细信息,我无法告诉您该幻数应该是多少,但您可能需要处理的最大信息块的大小至少是一个很好的起点。

    2) 如果您不需要文件中的每一位数据(您可以丢弃其中的一些信息),那么您只需要其中的一部分。如果您只需要选择的数据片段,那么如果它们被标记(这就是 XML 的用途),则更容易找到它们。有很多免费的 XML 解析器,或者您可以编写自己的。然后,您将搜索标签而不是任意行号,并且导致数据位于不同位置的文件更改不会影响您找到它的能力,如果它被标记,就像您只是要去按行号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-08
      • 1970-01-01
      • 1970-01-01
      • 2017-02-28
      • 1970-01-01
      • 1970-01-01
      • 2015-11-26
      • 2022-01-21
      相关资源
      最近更新 更多