在Qt库中有QByteArray和QDataStream类,它允许我使用非常容易使用的语法读取和写入memmory缓冲区中的变量:
QByteArray data = getData();
QDataStream stream( data );
double d = 0;
int i = 0;
stream >> d >> i;
如何仅使用stl流类实现simmilar行为? 例如,我有一个const char *数据和它的大小,所以我想构造std :: istream并从该数据中读取varible:
const char* data = getData();
size_t size = getSize();
membuffer buf( data, data + size );
std::istream str( buf );
double d = 0;
str >> d;
请注意,不应复制数据!
答案 0 :(得分:0)
假设您有一个固定大小的数据缓冲区及其大小,通过创建合适的流缓冲区来实现它是微不足道的:
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)) {
}
};
只是一个警告:创建一个流比复制相当多的数据更昂贵。也就是说,如果你想在循环中使用该流,你可能想要提供重置缓冲区的功能(可能与清除状态标志结合)。