【问题标题】:Fseek to a line number (with lines of variable length)Fseek 到一个行号(具有可变长度的行)
【发布时间】:2014-08-30 07:27:30
【问题描述】:

我有一个带有可变长度行的大文件 (~10GB),我想以编程方式转到不同的行号。有没有一种有效的方法来做到这一点?

【问题讨论】:

  • 你为什么要问,具体的用例是什么?
  • 这个非常大的文件是什么?
  • 请编辑您的问题以解释您是如何获得如此大的文件的。哪里来的?
  • @BasileStarynkevitch 这是一部短篇小说,或者可能是微软的保密协议:)
  • 就像@BasileStarynkevitch 说的那样,你能给我们提供更多线索吗?显然,这个庞大的文本文件中有什么?行可以排序吗?

标签: c fseek


【解决方案1】:

是的:建立一个索引。例如,只需一次您可以在包含各种行号的字节偏移量的一侧创建一个文本文件,如下所示:

line,offset
0,0
10000,48272
20000,93726

等等。然后,当您想转到第 13043 行时,只需跳转到偏移量 48272 并跳过另外 3043 个换行符。简单高效。

另一种方法是使行长保持不变。如果它们已经具有相似的长度,这将很有效,这样您就不会浪费太多空间。您可以使用\0 字符或空格或其他任何内容填充它们,然后像​​大矩阵一样索引文件(第 N 行在 N*LEN 字节处)。

最后,您可以简单地将行号写在行首。然后只需在文件中进行二进制搜索,跳到换行符,并检查下一个行号以知道是向后看还是向前看(甚至猜测多少)。

【讨论】:

  • 我会使用 gdbmsqlite 将其设为索引文件
  • 如果索引使用固定宽度格式可能会更好,这样您就可以跳转到索引文件中的右侧条目以查找文本文件中的位置。
  • @JonathanLeffler:也许,理论上你会得到 O(1) ......实际上这可能并不重要,因为你会在使用它之前将索引文件加载到内存中(可能)。不过,为你 +1。
【解决方案2】:

没有有效的方法来做到这一点。您需要扫描整个文件一次以记住行尾标记的结束时间。

实际上,您需要一个大循环,例如getline(3)

你可以记住例如每 100 行的偏移量,可能在一个大数组或使用 GDBM 或一些 Sqlite 数据库的某个索引文件中。

我的感觉是,你根本不应该有这么大的文本文件(随机访问一个巨大的文本文件是出现问题的征兆)。如果您需要随机访问这些数据,这不是存储此类数据的有效方式。例如,您可以预消化它以填充一些数据库等...可能您不应该将这么大的数据放在文本文件中,而应该直接放在数据库或其他任何东西中。

【讨论】:

    【解决方案3】:

    不能直接使用fseek,因为它只能将位置移动一个字节。

    如果效率要求来自您必须来回多次执行的事实,一个简单的解决方案可能是扫描整个文件并计算所有行长度,将它们存储在映射或数组中,然后使用值以准确地移动到您想要的位置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-13
      • 2014-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-28
      • 2015-08-09
      • 2013-04-29
      相关资源
      最近更新 更多