【问题标题】:istream for char buffer用于字符缓冲区的 istream
【发布时间】:2015-12-09 18:30:10
【问题描述】:

在 Qt 库中有 QByteArray 和 QDataStream 类,它们允许我以非常易于使用的语法读取和写入变量到内存缓冲区:

QByteArray data = getData();
QDataStream stream( data );
double d = 0;
int i = 0;
stream >> d >> i;

如何仅使用 stl 流类实现类似的行为? 例如,我有一个 const char* 数据和它的大小,所以我想构造 std::istream 并从该数据中读取变量:

const char* data = getData();
size_t size = getSize();

membuffer buf( data, data + size );
std::istream str( buf );
double d = 0;
str >> d;

注意不要复制数据!

【问题讨论】:

  • std::xstream 类具有QTextStream 的功能, QDataStream。 C++ 标准库中没有类似于QDataStream 的内容。一般来说,std::istream 对您的目的毫无用处。重新实现QDataStreamnot hard at all
  • 纠正无效假设后,这可能与this question 重复。
  • @KubaOber:鉴于请求是使用标准流执行类似的操作,那么您指出的问题(甚至更重要的是答案)显然是不是的答案。 ..
  • @DietmarKühl 标准流是大多数QTextStream 的替代品。如果您想要的只是二进制序列化,那么它们没有意义,而QDataStream 进行二进制序列化。这个问题是基于一个无效的假设。仅仅因为 QDataStreamstd::istream 在他们的名字中包含“stream”,并不能让一个替代另一个。

标签: c++ stl istream


【解决方案1】:

假设您有一个固定大小的数据缓冲区,并且它的大小可以通过创建合适的流缓冲区来实现:

struct membuf: std::streambuf {
     membuf(char* begin, char* end) {
         this->setg(begin, begin, end);
     }
};

这个简单的流缓冲区只是将流缓冲区“get-area”设置为[begin, end)的范围(begin被使用了两次,因为可以设置一个“放回区域”,在这种情况下是空的)。当没有更多字符要读取时,流将尝试调用underflow(),其默认实现指示失败。如果您想读取更多字符,您可以覆盖 underflow() 以在新设置的缓冲区中提供更多字符。

您可以使用此内存支持的流缓冲区创建流:

membuf       sbuf(begin, end);
std::istream in(&sbuf);
double d = 0;
if (in >> d) { // always check conversions from string to a value...
    // ...
}

为了更方便一点,流缓冲区和流的创建也可以捆绑到一个类中。有一个小技巧,应该合理地更早地创建流缓冲区,但它是可行的:

class imemstream: private virtual membuf, public std::istream {
public:
    imemstream(char* begin, char* end)
        : membuf(begin, end)
        , std::ios(static_cast<std::streambuf*>(this))
        , std::istream(static_cast<std::streambuf*>(this)) {
    }
};

不过,只是一个警告:创建流比复制大量数据更昂贵。也就是说,如果您想在循环中使用该流,您可能需要提供重置缓冲区的功能(可能与清除状态标志结合使用)。

【讨论】:

  • QDataStream 与文本转换无关,不过……它是用于二进制序列化的二进制流,而不是文本序列化。
  • @KubaOber:请求是使用str &gt;&gt; dstd::istream 读取。那显然是在读取文本格式的数据。
  • Kuba Ober 是正确的,我不需要读取和操作字符串,我需要二进制反序列化。
  • @Jeka: std::istreamoperator&gt;&gt;() 用于将文本转换为值。在这种情况下,您需要一个不同的工具。标准 C++ 库没有任何用于将二进制数据转换为值的工具。
猜你喜欢
  • 1970-01-01
  • 2011-08-14
  • 1970-01-01
  • 1970-01-01
  • 2020-10-24
  • 1970-01-01
  • 2010-10-13
  • 2017-12-29
  • 2018-04-24
相关资源
最近更新 更多