C++ 如何从uint8\t向量创建istream?

C++ 如何从uint8\t向量创建istream?,c++,C++,我正在将通过网络获取数据的能力添加到过去只读取本地文件的代码中。我使用的网络库以向量的形式发送和接收数据。我希望能够在读取文件后重用处理数据的代码,但该代码需要std::istream,有没有办法让istream读取向量数据?这是相同的数据,所以我觉得应该有一种方法,但我还没有找到或想出如何做到这一点的代码 当前代码: std::ifstream stream("data.img", std::ios::in | std::ios::binary | std::ios::ate);

我正在将通过网络获取数据的能力添加到过去只读取本地文件的代码中。我使用的网络库以
向量的形式发送和接收数据。我希望能够在读取文件后重用处理数据的代码,但该代码需要std::istream,有没有办法让istream读取向量数据?这是相同的数据,所以我觉得应该有一种方法,但我还没有找到或想出如何做到这一点的代码

当前代码:

    std::ifstream stream("data.img", std::ios::in | std::ios::binary | std::ios::ate);

    if (!stream.is_open())
    {
        throw std::invalid_argument("Could not open file.");
    }
    // the arg for processData is std::istream
    processData(stream);
网络框架:

    vector<uint8_t> data = networkMessage.data;

    // need some way to create istream from data
    std::istream stream = ?

    processData(stream);
    stream.close();
vector data=networkMessage.data;
//需要一些从数据创建istream的方法吗
std::istream流=?
处理数据(流);
stream.close();

有没有办法做到这一点,或者我选错了树?

您可以通过将数据分配给并使用绑定来实现这一点(撇开
无符号字符
有符号字符
的转换问题不谈):


std::basic_istream
从关联的
std::basic_streambuf
派生类获取其数据。STL为文件I/O和字符串I/O提供此类类,但不为内存I/O或网络I/O提供此类类

您可以轻松编写(或找到第三方)基于内存的
streambuf
类,该类使用
std::vector
作为其底层缓冲区,然后您可以构造一个
std::istream
使用该内存
streambuf
。例如(使用来自的
imemstream
类 ):

std::vector&data=networkMessage.data;
imemstream流(reinterpret_cast(data.data()),data.size());
处理数据(流);

这将适用于任何类型的向量,而不仅仅是
uint8\t

性病
模板
自动生成istringstream\u std\u 1(const std::vector&v)->std::istringstream
{
使用名称空间std::string_文本;
std::字符串str;
用于(自动和电气:v)
{
str+=std::to_字符串(e)+“s;
}
//尾随空格不是问题
返回std::istringstream{str};
}
std算法
模板
自动生成istringstream\u std\u 2(const std::vector&v)->std::istringstream
{
std::stringstream-ss;
std::copy(v.begin(),v.end(),std::ostream_迭代器(ss,“”);
//尾随空格不是问题
返回std::istringstream{ss.str()};
}
促进
模板
自动生成istringstream\u boost(const std::vector&v)->std::istringstream
{
使用boost::Adapters::transformed;
使用boost::算法::join;
返回std::istringstream{
join(v | transformed([](int a){return std::to_string(a);}),“”)};
}

归属:


< C++ >实际上C++有一个类,你可以这样使用:

    vector<uint8_t> data = ...;

    // need some way to create istream from data
    std::istrstream stream(reinterpret_cast<const char*>(data.data()), data.size());

    processData(stream);
向量数据=。。。; //需要一些从数据创建istream的方法吗 std::istrstream流(reinterpret_cast(data.data()),data.size()); 处理数据(流);
据我所知,这并没有复制数据,不像其他答案。但是,它在C++98中也被弃用,因此您可能需要编写自己的等效程序

  • istream
    是原始数据的参考。它不保存数据,只是一个访问者,方法是保留一些
    char*
    指针作为数据内存地址的开始和结束

  • 向量中的存储是连续的,但通过使用
    push_back()
    ,存储地址可能会更改,(复制内部向量)

  • 因此,可以将
    istream
    转换为
    常量向量

  • 参考文件

    最短示例

    类向量buf:public std::streambuf{ 公众: vectorbuf(标准::vector&v){ setg((char*)v.data(),(char*)v.data(),(char*)(v.data()+v.size()); } ~vectorbuf(){} }; //用法: 向量arr{11,12,13,14,15,16}; 向量基函数vbuf(arr); std::istream is(&vbuf); 完全错误的示例代码

    #包括
    #包括
    #包括
    #包括
    使用名称空间std;
    模板
    类vectorbuf:public std::streambuf{
    公众:
    向量BUF(标准::向量和v):_值(v){
    char*bptr=(char*)_value.data();
    char*eptr=(char*)(_value.data()+_value.size());
    setg(bptr、bptr、eptr);
    
    CoutInstance
    std::istreamstream
    源于
    std::istream
    ,您可以将
    iss
    直接传递到
    processData()
    ,而无需声明中间变量:
    processData(iss);
    此外,此解决方案的缺点是必须首先将
    std::vector
    数据复制到
    std::string
    ,如
    processData()
    无法直接读取
    std::vector
    。@Remy我这样设计示例是为了清晰。它可能是为了清晰,但肯定不是为了效率/性能,尤其是对于大数据。是的,这会将数据复制到
    字符串中。不太可能是您想要的。这里有两个副本。如果使用boost,您可以直接使用由于涉及到所有的复制,这是非常低效的。这就是獾(尽管这种反对让我感到害怕,我个人使用的是Remy链接到的解决方案)可能的复制
    
    template <class T>
    auto make_istringstream_std_1(const std::vector<T>& v) -> std::istringstream
    {
        using namespace std::string_literals;
        std::string str;
    
        for (auto& e : v)
        {
            str += std::to_string(e) + " "s;
        }
        // the trailing space is not an issue
    
        return std::istringstream{str};
    }
    
    template <class T>
    auto make_istringstream_std_2(const std::vector<T>& v) -> std::istringstream
    {
        std::stringstream ss;
        std::copy(v.begin(), v.end(), std::ostream_iterator<int>(ss, " "));
        // the trailing space is not an issue
    
        return std::istringstream{ss.str()};
    }
    
    template <class T>
    auto make_istringstream_boost(const std::vector<T>& v) -> std::istringstream
    {
        using boost::adaptors::transformed;
        using boost::algorithm::join;
    
        return std::istringstream{
            join(v | transformed([](int a) { return std::to_string(a); }), " ")};
    }
    
        vector<uint8_t> data = ...;
    
        // need some way to create istream from data
        std::istrstream stream(reinterpret_cast<const char*>(data.data()), data.size());
    
        processData(stream);