【问题标题】:Fast accessing file position in ifs() C++在 ifs() C++ 中快速访问文件位置
【发布时间】:2018-07-04 15:44:39
【问题描述】:

信息:在 txt 文件中存储位置、关闭文件,然后使用 c++ 在同一位置打开它的最佳方法是什么?

我有一个大文本文件,我需要对其进行分块解析并输入到某个系统中。到目前为止,我在 ifstream 中加载文件,然后在 getlines 中加载,直到找到我需要的数据(假设数据位于 {x} 位置)。在此之后我关闭文件,处理数据,现在我需要继续从大文件中提供数据。所以我再次打开文件,并获取行,直到这次我到达位置 {x+d} (d 是我读取的数据的偏移量)......

很容易看出,我不是通过文件一次,而是通过文件 (1d + 2d + ... + (N-1)d + Nd) ~ d*N^2 次。现在我想在d之后保存文件中的位置,关闭文件,然后在同一位置立即打开文件。可以为此使用什么?

【问题讨论】:

  • 您将使用与将位置存储在一个非常小的文件中相同的东西。无论如何,文件的大小没有实质性的区别。
  • @SamVarshavchik:这并不完全正确。对于大文件(尤其是超过 2GB 的文件),您需要更加小心用于存储位置的数据类型。
  • 看起来你有seekg标签?
  • Possible d... 那是 C.
  • @Sadikov -- 首先,有问题的文件是否有固定的行长?如果是这样,您就不需要getline,因为您可以简单地使用偏移量来计算您在文件中的哪一行/哪一列。

标签: c++ parsing ifstream seekg


【解决方案1】:

您不能在启用换行翻译的情况下执行此操作(标准称为“文本模式”),因为回溯到该位置需要标准库扫描文件的整个前面以找到 N 个字符 - 不是 -双重计算换行符。可变长度编码的翻译(例如,在 UTF-8 和 UCS 之间)会导致类似的问题。

解决方案是关闭换行转换(标准称为“二进制模式”)和任何其他涉及可变长度编码的转换,并自行处理。在关闭所有翻译的情况下,“文件位置”是操作系统直接用于执行文件 I/O 的数字,因此具有非常高效的潜力(实际上是否有效取决于标准库的实现细节)。

【讨论】:

  • @Sadikov:如果您关闭换行符,则不会阻止您调用getline(),但根据生成文件的软件,行结尾可能是 \r\n、\r 或\n,而不仅仅是\n,这会影响getline的参数。操作系统用来执行文件 I/O 的数字是标准库传递给操作系统文件 I/O 函数的文件位置,例如在 Windows 上,这将是 @987654324 的 OffsetOffsetHigh 成员@ 结构体。关闭翻译时,tellseek 使用的逻辑位置与操作系统位置相同。
  • @Sadikov:这是期望值,尽管可能有一个脑死库不实现“立即跳转”路径,并且无论翻译是打开还是关闭都只是从头开始计数.只需测量seekg(large number) 的时间长度 + 一个固定长度的小读取时间,您就可以轻松测试自己是否走上了快车道。
  • 您对此声明有参考吗?我的印象是,如果您使用 tell 返回的位置调用 seek,则无论翻译如何,您都将精确地恢复文件位置(除非您的多字节编码是上下文的)。
  • @Ben:我真的不相信会是这样,这就是为什么我希望看到一个参考而不是你的断言。对于文本文件,您只能搜索到以前的 seekpos 或 seekoff 返回的位置,这将是一个适合将文件位置重置为其以前值的值,而无需调用 Schlemiel 的服务。
  • C++ 最终在这里遵循 C 库,因此值得引用第 7.21.9.4 节的段落。 C 标准的第 2 节,其中描述了 ftell 的返回值:“对于文本流,其文件位置指示符包含未指定的信息,可由 fseek 函数用于将流的文件位置指示符返回到当时的位置ftell 调用;两个这样的返回值之间的差异不一定是对写入或读取字符数的有意义的度量。"
猜你喜欢
  • 2017-05-07
  • 2015-11-04
  • 1970-01-01
  • 2017-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-31
相关资源
最近更新 更多