【发布时间】:2017-06-12 15:27:58
【问题描述】:
背景
我实现了一个 JSON 解析器并提供了一个 operator>> 函数来解析 std::ifstream。为了加快读取速度,我将 16 KB 复制到缓冲区中,并让解析器从缓冲区中读取。一个小型基准测试表明,这比直接使用 std::ifstream::get 或 std::ifstream::read 更快。
当前(错误?)实现
当我成功读取 JSON 值时,我想将缓冲区中所有不必要的字节“放回”到流中,以便随后使用相同的 std::istream 调用 operator>> 继续在第一次调用结束的地方进行解析。我目前像这样实现这个“放回”:
is.clear();
is.seekg(start_position + static_cast<std::streamoff>(processed_chars));
is.clear();
因此,is 是输入文件流,start_position 是 is.tellg() 的初始值,processed_chars 是解析器读取的字符数。
这适用于 GCC 和 Clang 以及 OSX 和 Linux,但 MSVC 2015 和 MSVC 2017 无法将输入流带入所需状态。
我的问题
显然,我在这里做错了什么。不同的编译器不应该表现得如此不同。
clear()调用已经是使代码在 GCC/Clang 下运行的反复试验的结果。(a) 使用缓存从已打开的
std::ifstream读取和 (b) 能够在最后一个处理的字符之后(而不是在最后一个缓存的字符之后)恢复解析的正确方法是什么?有没有更好的方法来快速读取已经打开的
std::ifstream?正如我上面提到的,删除缓存会使解析器变慢。
(对这个幼稚的问题和糟糕的实现表示歉意!我没有找到解决已经打开的std::ifstream 或者可以“放回”已经缓存的字符的答案。)
【问题讨论】:
-
hmmm 你真的需要它在 MSVC 下编译吗?您甚至可以在 linux/Mac 机器上使用 GCC/Clang 创建 Windows 可执行文件,对吧?
-
您可以通过编写自定义
::std::streambuf实现来创建自定义缓冲文件流。 -
@niceman 最后,我只发布了一个可以在任何地方编译的标头,请参阅github.com/nlohmann/json
-
@VTT 我可以将此自定义缓冲区与传递的
std::ifstream对象一起使用吗?以及如何将字符从缓冲区“放回”到流中? -
通常你会在创建时将
streambuf实例指针传递给istream,并且根本不需要使用ifstream。只要您在streambuf实现中提供相应的重载,stream 就会处理“放回”和其他操作。