如何使用缓冲区正确读取已打开的std :: ifstream

时间:2017-06-12 15:27:58

标签: c++ caching ifstream

背景

我实现了一个JSON解析器,并提供了一个operator>>函数来解析std::ifstream。为了加快读取速度,我将16 KB复制到一个缓冲区中,让我的解析器从缓冲区中读取。一个小的基准测试显示,这比直接使用std::ifstream::getstd::ifstream::read更快。

当前(错误?)实施

当我成功读取JSON值时,我想"放回"从缓冲区到流的所有不必要的字节,因此后续调用operator>>并使用相同的std::istream继续解析第一个调用结束的位置。我目前正在实施这个"放回"像这样:

is.clear();
is.seekg(start_position + static_cast<std::streamoff>(processed_chars));
is.clear();

因此,is是输入文件流,start_positionis.tellg()的初始值,processed_chars是解析器读取的字符数。

这适用于GCC和Clang与OSX和Linux,但MSVC 2015和MSVC 2017无法将输入流带入所需状态。

我的问题

  1. 显然,我在这里做错了。不同的编译器不应该表现得如此不同。 clear()调用已经是试验和错误的结果,以使代码与GCC / Clang一起运行。

  2. 正确的方法是(a)从已经打开的std::ifstream使用缓存读取,以及(b)能够在最后处理的字符之后(而不是在最后一个缓存的字符之后)继续解析)?

  3. 有没有更好的方法快速阅读已经开放的std::ifstream?正如我上面提到的,删除缓存会使解析器变慢。

  4. (对于天真的问题和可怕的实施道歉!我没有找到一个答案,处理已经开放的std::ifstream或者可以&#34;放回&#34;已经缓存的字符。)

1 个答案:

答案 0 :(得分:5)

如果您在文本模式下打开文件流,则无效:

is.seekg(start_position + static_cast<std::streamoff>(processed_chars));

...因为根据标准,seekg / tellg与处理的字符数没有直接关系(这实际上取决于操作系统)。

以下是您可能选择的选项(无法提供您在问题中提供的详细信息):

  • 使用putback放回您阅读但未使用的字符;
  • 使用tellg获取正确的位置。

这样的事情可能是:

// is is the istream
auto tg = is.tellg();
is.read(buffer, BUFFER_SIZE);
 // process...
is.seekg(tg); // valid
is.ignore(processed_chars);