strstream 可以直接使用标准字符串的缓冲区吗

Can an strstream directly use the buffer of a standard string

提问人:Lorah Attkins 提问时间:5/31/2023 最后编辑:Lorah Attkins 更新时间:6/1/2023 访问量:184

问:

鉴于 strstream 具有以下构造函数:

strstream( char* s, int n, std::ios_base::openmode mode);

我想知道我是否可以直接使用标准字符串底层的缓冲区,当然是在“只读”模式下,以避免缓冲区重新分配的奇怪副作用:

std::string buffer("Dummy Data");
std::strstream ss(
  const_cast<char *>(buffer.data()), buffer.length(), std::ios_base::in);

std::string other;
ss >> other;
std::cout << other << std::endl;

令我惊讶的是,上面的代码最终变成了一个空字符串。在文档中有一个示例,其中 C 数组用作 的静态缓冲区,所以我想知道它不能使用缓冲区内容的原因是什么?otherstrstreamstd::string

注意:我不能使用,因为有问题的平台有一个 VS 实现,其大小限制为 4GB,如此处所述std::stringstream


更新:

我看到使用(如示例中所示)几乎可以使我的代码正常工作。现在最大的问题(根据我得到的评论)是它早已被弃用。也许 boost iostreams 中有一些东西可以提供帮助,但对该库有很多了解。std::ios_base::appstrstream

C++ C++11 字符串流

评论

1赞 Pepijn Kramer 5/31/2023
对于这样的文件大小,我将开始研究内存映射文件并从中读取。有平台独立的库。
3赞 Alan Birtles 5/31/2023
strstream25 年前被弃用了,你真的不应该使用它
0赞 Lorah Attkins 5/31/2023
@AlanBirtles 还有其他选择吗?我正在使用的代码使用流来序列化数据(例如),然后将这些流刷新到磁盘。内容已经“在内存中”,所以我看不出内存映射文件的建议对我有什么作用,除非我使用它(内存映射文件)作为我的缓冲区并检查是否存在类似的语法(我的意思是类似于std::stringstreammyStream << delimiter << current_data[i] << ...stream << content)
1赞 Quxflux 5/31/2023
这被明确标记为 C++11,但只是为了完整起见: C++23 std::spanstream 是您想要使用的: stackoverflow.com/questions/67924325/...
2赞 john 5/31/2023
@LorahAttkins 不完全遵循您的要求,但为什么不编写自己的派生类呢?然后它可以做任何你想做的事std::streambuf

答:

3赞 vvv444 5/31/2023 #1

与其使用 C++98 中弃用的 strstream,并且由于编译器中提到的 4GB 限制,您不能使用其标准推荐的替代品(即字符串流),则可以使用 Boost 的缓冲区流作为替代方案,如下所示

#include <iostream>
#include <boost/interprocess/streams/bufferstream.hpp>

namespace bi = boost::interprocess;

int main()
{
    std::string buffer("Dummy Data");

    bi::bufferstream ss(&buffer[0], buffer.size());

    std::string other;
    ss >> other;
    std::cout << other << std::endl;

    return 0;
}

这个类似乎只是头文件,所以不需要编译boost。无论如何,如果使用 Visual Studio,则可以使用 vcpkg 轻松安装 boost。

注意:正如 Peppin 对这个问题的评论中提到的,如果您的数据来自文件,那么与其将其完全读取到内存中,不如只使用内存映射文件。在这个答案中,有一个很好的例子来说明如何做到这一点。

评论

0赞 Lorah Attkins 5/31/2023
这是一个很好的答案,因为该库还包含用于文件映射的跨平台实用程序,根据其中一条评论,这应该是非常大的数据集的可用后备
0赞 vvv444 6/1/2023
@LorahAttkins是的,这个评论是非常正确的。如果您的数据来自文件,则将其完全读取到 RAM 是没有意义的。我只是试着从狭义上回答你的问题。但如果你愿意,我也可以提供文件映射的答案。
0赞 Lorah Attkins 6/1/2023
我陷入了困境,因为我忽略了仅适用于静态缓冲区,但允许使用来填充默认构造的实例,即没有缓冲区的实例(导致 UB)。最终用于动态填充的流,并“避免复制现有缓冲区。顺便说一句,我恢复了 c++11 标签,因为这是我的目标语言标准。如果我没有标准要求,我可以使用它,这不会带来额外的依赖关系。bufferstreamoperator<<vectorstreambufferstreamstd::spanstream