【问题标题】:How to convert from stringstream to unsigned char vector and vice versa?如何从字符串流转换为无符号字符向量,反之亦然?
【发布时间】:2018-12-15 21:47:45
【问题描述】:

我有std::stringstream ss;,包含我想放入std::vector<unsigned char> my_vector; 的二进制数据。然后,我想使用my_vector 并用它来创建一个与ss 相同的新std::stringstream new_ss

我已经尝试做类似于这个问题的答案的事情:

Is there a more efficient way to set a std::vector from a stream?

还有这个问题:

C++: vector to stringstream

结束:

std::copy(std::istream_iterator<unsigned char>(ss),
          std::istream_iterator<unsigned char>(),
          std::back_inserter(my_vector));

然后:

std::copy(my_vector.begin(), 
          my_vector.end(),
          std::ostream_iterator<unsigned char>(new_ss));

但是ssnew_ss 不一样。我怀疑这个问题可能与忽略的空格有关,所以我尝试用这种方式制作向量:

    std::string const& s = ss.str();
    my_vector.reserve(s.size());
    my_vector.assign(s.begin(), s.end());

但这并没有解决问题。

任何关于可能出错的想法或解决此问题的更好方法的建议将不胜感激。

【问题讨论】:

  • 你使用std::ios::binary构造字符串流了吗?
  • 拥有一个minimal reproducible example 并知道字符串的不同之处会有所帮助...(“不一样”并不是非常精确)
  • @stringstreams 来自 grain::BinaryInputArchive iarchive(ss) 并且是序列化对象的结果。

标签: c++ serialization stdvector stringstream c++-standard-library


【解决方案1】:

我怀疑这将是一种相当有效的方法:

std::string const test_data = "hello world";

std::stringstream ss(test_data);

// discover size of data in stringstream
auto bof = ss.tellg();
ss.seekg(0, std::ios::end);
auto stream_size = std::size_t(ss.tellg() - bof);
ss.seekg(0, std::ios::beg);

// make your vector long enough
std::vector<unsigned char> v(stream_size);

// read directly in
ss.read((char*)v.data(), std::streamsize(v.size()));

// Now put it into a new stream object
std::stringstream new_ss;

// direct write again
new_ss.write((char const*)v.data(), std::streamsize(v.size()));

// check the result is the same as the original data
assert(new_ss.str() == test_data);

这些可以被包装成函数以使它们更容易:

std::vector<unsigned char> to_vector(std::stringstream& ss)
{
    // discover size of data in stream
    ss.seekg(0, std::ios::beg);
    auto bof = ss.tellg();
    ss.seekg(0, std::ios::end);
    auto stream_size = std::size_t(ss.tellg() - bof);
    ss.seekg(0, std::ios::beg);

    // make your vector long enough
    std::vector<unsigned char> v(stream_size);

    // read directly in
    ss.read((char*)v.data(), std::streamsize(v.size()));

    return v;
}

std::stringstream to_stream(std::vector<unsigned char> const& v)
{
    std::stringstream ss;
    ss.write((char const*)v.data(), std::streamsize(v.size()));
    return ss;
}

int main()
{
    std::string const test_data = "hello world";

    std::stringstream ss(test_data);

    auto v = to_vector(ss);

    auto new_ss = to_stream(v);

    assert(new_ss.str() == test_data);
}

【讨论】:

  • 也许reinterpret_cast&lt;char const*&gt;(v.data()) 更适合 w.r.t. (char const*)v.data():更清楚地表明我们正在使用这个“有风险”的功能stackoverflow.com/a/332086/2436175
【解决方案2】:

使用std::istream_iterator&lt;T&gt; 迭代器或std::ostream_iterator&lt;T&gt; 肯定不会工作(如果输入)并且只是不必要的慢(如果输出)。问题是std::istream_iterator&lt;T&gt; 跳过了前导空格,并且两个迭代器都通过格式化的接口进行了各种检查,这些检查并没有真正的帮助。

您可以使用std::istreambuf_iterator&lt;char&gt;std::ostreambuf_iterator&lt;char&gt;。不过,我认为通过字符串接口进行转换更有效。

【讨论】:

    【解决方案3】:

    std::vector 有一个重载构造函数,它接受一对定义新向量内容序列的输入迭代器。

    std::stringstream ss;
    
    // Fill in your stringstream, then:
    
    std::vector<unsigned char> my_vector{
        std::istreambuf_iterator<char>{ss},
        std::istreambuf_iterator<char>{}
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-15
      • 2011-11-08
      • 1970-01-01
      • 2011-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多