C ++中是否有二进制内存stream?
我通常使用stringstream
来写入内存中的string。 有没有办法写入二进制模式的字符缓冲区? 考虑下面的代码:
stringstream s; s << 1 << 2 << 3; const char* ch = s.str().c_str();
ch
的内存将如下所示:0x313233 – 字符1,2和3的ASCII代码。我正在寻找一种方法来编写二进制值本身。 也就是说,我想在内存中的0x010203。 问题是我想能够写一个函数
void f(ostream& os) { os << 1 << 2 << 3; }
并决定在什么样的stream使用。 像这样的东西:
mycharstream c; c << 1 << 2 << 3; // c.data == 0x313233; mybinstream b; b << 1 << 2 << 3; // b.data == 0x010203;
有任何想法吗?
要读取二进制数据并将其写入stream(包括stringstream),请使用read()和write()成员函数。 所以
unsigned char a(1), b(2), c(3), d(4); std::stringstream s; s.write(reinterpret_cast<const char*>(&a), sizeof(unsigned char)); s.write(reinterpret_cast<const char*>(&b), sizeof(unsigned char)); s.write(reinterpret_cast<const char*>(&c), sizeof(unsigned char)); s.write(reinterpret_cast<const char*>(&d), sizeof(unsigned char)); s.read(reinterpret_cast<char*>(&v), sizeof(unsigned int)); std::cout << std::hex << v << "\n";
这给我的系统0x4030201
。
编辑:为了使插入和提取操作符(<<和>)透明地工作,最好的办法是创build一个派生的streambuf来执行正确的操作,并将其传递给您想要使用的任何stream。
那么,只是使用字符,而不是整数。
s << char(1) << char(2) << char(3);
超载一些不寻常的操作员工作得很好。 下面我select重载<=,因为它具有与<<左右相关的相同性,并且具有某种亲密的外观和感觉。
#include <iostream> #include <stdint.h> #include <arpa/inet.h> using namespace std; ostream & operator<= (ostream& cout, string const& s) { return cout.write (s.c_str(), s.size()); } ostream & operator<= (ostream& cout, const char *s) { return cout << s; } ostream & operator<= (ostream&, int16_t const& i) { return cout.write ((const char *)&i, 2); } ostream & operator<= (ostream&, int32_t const& i) { return cout.write ((const char *)&i, 4); } ostream & operator<= (ostream&, uint16_t const& i) { return cout.write ((const char *)&i, 2); } ostream & operator<= (ostream&, uint32_t const& i) { return cout.write ((const char *)&i, 4); } int main() { string s("some binary data follow : "); cout <= s <= " (machine ordered) : " <= (uint32_t)0x31323334 <= "\n" <= s <= " (network ordered) : " <= htonl(0x31323334) ; cout << endl; return 0; }
有几个缺点:
-
<=的新含义可能会使读者感到困惑或导致意想不到的结果:
cout <= 31 <= 32;
将不会给出相同的结果
cout <= (31 <= 32);
-
如上例所示,在阅读代码时,没有明显提到Endianess。
-
它不能简单地与<<混合,因为它不属于同一组优先。 我通常使用括号来澄清如:
( cout <= htonl(a) <= htonl(b) ) << endl;
对于这个用例,我实现了一个“原始转换运算符”:
template <typename T, class... StreamArgs> inline std::basic_ostream<StreamArgs...> & operator <= (std::basic_ostream<StreamArgs...> & out, T const & data) { out.write(reinterpret_cast<char const *>(&data), sizeof(T)); return out; }
把它放在方便的地方,像这样使用它:
std::cout <= 1337 <= 1337ULL <= 1337. <= 1337.f;
优点:
- 可链接
- 自动
sizeof()
- 同样需要数组和结构/类实例
缺点:
- 对非POD对象不安全:泄漏指针和填充
- 输出是平台特定的:填充,字节数,整数types