在 C++ 中寻找 MemoryStream

发布于 2024-09-06 05:13:43 字数 429 浏览 11 评论 0原文

在 C# 的奇妙世界中,我可以创建一个内存流而不指定其大小, 写入其中,然后只获取底层缓冲区。

我怎样才能在 C++ 中做同样的事情?基本上我需要做的是:

memory_stream  ms(GROW_AS_MUCH_AS_YOU_LIKE);

ms << someLargeObjects << someSmallObjects << someObjectsWhosSizeIDontKnow;

unsigned char* buffer = ms.GetBuffer();
int bufferSize = ms.GetBufferSize();

rawNetworkSocket.Send(buffer, bufferSize);

顺便说一句,我在我的项目中得到了提升,尽管我不太熟悉它。

谢谢。

In the wonderful world of C# i can create a memory stream without specifying its size,
write into it and then just take the underlying buffer.

How can i do the same in c++? basicly i need to do:

memory_stream  ms(GROW_AS_MUCH_AS_YOU_LIKE);

ms << someLargeObjects << someSmallObjects << someObjectsWhosSizeIDontKnow;

unsigned char* buffer = ms.GetBuffer();
int bufferSize = ms.GetBufferSize();

rawNetworkSocket.Send(buffer, bufferSize);

By the way I have boost in my project though I'm not all that familiar with it.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

无悔心 2024-09-13 05:13:43
#include <sstream>

std::ostringstream  buffer; // no growth specification necessary
buffer << "a char buffer" << customObject << someOtherObject;

std::string contents = buffer.str();
size_t bufferSize = contents.size();

rawNetworkSocket.Send(contents); // you can take the size in Send

使用这种方法,您必须在收到结果的地方解析结果(因为上面的代码只是将您的数据转换为非结构化字符串。

它的另一个问题是,由于 C++ 不支持反射,您必须定义运算符 < Custom 类的代码:

template<typename C, typename T>
std::basic_ostream<C,T>& operator << (
    std::basic_ostream<C,T>& out, const Custom& object)
{
    out << object.member1 << "," << object.member2 /* ... */ << object.memberN;
    return out;
}

如果您想要结构化序列化,请查看 boost::序列化

#include <sstream>

std::ostringstream  buffer; // no growth specification necessary
buffer << "a char buffer" << customObject << someOtherObject;

std::string contents = buffer.str();
size_t bufferSize = contents.size();

rawNetworkSocket.Send(contents); // you can take the size in Send

Using this approach you will have to parse the result where you receive it (as the code above just transforms your data into an unstructured string.

Another problem with it is that since C++ doesn't support reflection, you will have to define operator << for your objects. This is the code for a Custom class:

template<typename C, typename T>
std::basic_ostream<C,T>& operator << (
    std::basic_ostream<C,T>& out, const Custom& object)
{
    out << object.member1 << "," << object.member2 /* ... */ << object.memberN;
    return out;
}

If you want structured serialization, have a look at boost::serialization.

漫雪独思 2024-09-13 05:13:43

为此,您可能需要查看 std::stringstream 。该流将根据需要增长。除非您想将对象保留为二进制而不是 ASCII,在这种情况下您可以查看 Streambuf 对象和实现。

请注意,C++ 没有反射或双重/多重分派,因此您必须自己为未知大小的对象提供支持:

class unknown_base {
   virtual void dump( std::ostream & ) const;
};
std::ostream& operator<<( std::ostream& o, unknown_base const & obj ) {
   obj.dump( o );
   return o;
}
std::string serialize( std::vector<unknown_base*> const & data ) {
   std::ostringstream st;
   for ( std::vector<unknown_base*>::const_iterator it = data.begin(), end = data.end();
         it != end; ++it ) {
      st << **it; // double dereference: iterator, pointer
   }
   return st.str();
}

You may want to look at std::stringstream for that purpose. The stream will grow as required. Unless you want to leave the objects in binary instead of ASCII, in which case you could take a look at the streambuf objects and implementations.

Note that C++ does not have reflection or double/multiple dispatch, so you will have to provide support for the unknown sized object yourself:

class unknown_base {
   virtual void dump( std::ostream & ) const;
};
std::ostream& operator<<( std::ostream& o, unknown_base const & obj ) {
   obj.dump( o );
   return o;
}
std::string serialize( std::vector<unknown_base*> const & data ) {
   std::ostringstream st;
   for ( std::vector<unknown_base*>::const_iterator it = data.begin(), end = data.end();
         it != end; ++it ) {
      st << **it; // double dereference: iterator, pointer
   }
   return st.str();
}
随波逐流 2024-09-13 05:13:43

在Boost方面,有 Iostreams ,它是非常相似。

On Boost side there is Iostreams which is very similiar.

挽清梦 2024-09-13 05:13:43

由于您正在谈论网络,因此您似乎非常想创建某种消息并通过线路发送它。

有一些库可以创建消息并为这些消息生成 API,其中最著名的是 Google Protocol Buffers(简称 protobuf)。它允许您在短文件(自定义格式)中描述消息的语法,然后自动生成 API 以用 C++/Python/Java 解码此消息

优点包括:

  • 互操作性,这也意味着可以使用脚本检查消息这里的语言,调试时很方便。
  • 版本处理(向后和向前兼容性),因为我们知道您很快就会修改消息,但可能不会立即升级所有
  • 文本/二进制输出。文本便于调试,当每个位都计数时需要二进制

此外,可以使用文本输出并使用 LZO 等对其进行压缩以获得一些空间:)

Since you are talking about network, it seems awfully like you want to create some kind of message and send it over the wire.

There are libraries to create messages and generate APIs for these messages, the most famous being Google Protocol Buffers (protobuf for short). It lets you describe the syntax of your message in a short file (custom format) and then automatically generate the API to decode this message in C++ / Python / Java

Advantages include:

  • interoperability, which also mean the possibility of inspecting a message with a scripting language here, handy when debugging.
  • version handling (backward and forward compatibility), because we know you'll soon modify the message but perhaps not upgrade everything at once
  • text / binary output. Text is handy for debugging, Binary is required when every bit count

Also, it's possible to use the text output and compress it with LZO or such to gain some space :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文