ищу MemoryStream в C ++ - PullRequest
       36

ищу MemoryStream в C ++

3 голосов
/ 22 июня 2010

В прекрасном мире 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);

Кстати, в моем проекте есть импульс, хотя я не настолько знаком с ним.

Спасибо.

Ответы [ 4 ]

5 голосов
/ 22 июня 2010
#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 ++ не 'Для поддержки рефлексии вам нужно определить оператор << для ваших объектов. Это код для <code>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:: сериализации .

2 голосов
/ 22 июня 2010

Вы можете посмотреть на 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();
}
1 голос
/ 22 июня 2010

На стороне Boost Iostreams , что очень похоже.

0 голосов
/ 22 июня 2010

Поскольку вы говорите о сети, кажется ужасно, что вы хотите создать какое-то сообщение и отправить его по сети.

Существуют библиотеки для создания сообщений и генерации API для этих сообщений, наиболее известными из которых являются Google Protocol Buffers (protobuf для краткости). Это позволяет вам описать синтаксис вашего сообщения в коротком файле (пользовательский формат), а затем автоматически сгенерировать API для декодирования этого сообщения в C ++ / Python / Java

Преимущества включают в себя:

  • совместимость, что также означает возможность проверки сообщения на языке сценариев, что удобно при отладке.
  • обработка версий (обратная и прямая совместимость), потому что мы знаем, что вы скоро измените сообщение, но, возможно, не обновите все сразу
  • текстовый / двоичный вывод. Текст удобен для отладки, двоичный код требуется при подсчете каждого бита

Кроме того, можно использовать вывод текста и сжать его с помощью LZO или чего-то подобного, чтобы получить некоторое пространство:)

...