Более простой способ создать C++ memorystream из (символ*, size_t), не копируя данные?

Я ничто не мог найти готовым, таким образом, я придумал:

class membuf : public basic_streambuf<char>
{
public:
  membuf(char* p, size_t n) {
    setg(p, p, p + n);
    setp(p, p + n);
  }
}

Использование:

char *mybuffer;
size_t length;
// ... allocate "mybuffer", put data into it, set "length"

membuf mb(mybuffer, length);
istream reader(&mb);
// use "reader"

Я знаю о stringstream, но это, кажется, не может работать с двоичными данными данной длины.

Я изобретаю свое собственное колесо здесь?

Править

  • Это не должно копировать входные данные, просто создавать что-то, что выполнит итерации по данным.
  • Это должно быть портативно - по крайней мере, это должно работать и под gcc и под MSVC.
29
задан Community 5 September 2012 в 19:25
поделиться

3 ответа

Я предполагаю, что ваши входные данные являются двоичными (не текстовыми), и что вы хотите извлечь куски двоичных данных из него. Все без копирования ваших входных данных.

Вы можете комбинировать Boost :: yoStreams :: Basic_array_Source и Boost :: IoStreams :: Stream_Buffer (из Boost.ioStreams ) С Boost :: Архив :: Binary_iarchive (из BOOST.Serialization ) Чтобы иметь возможность использовать удобную добычу >> операторы для чтения кусков двоичных данных.

#include <stdint.h>
#include <iostream>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/archive/binary_iarchive.hpp>

int main()
{
    uint16_t data[] = {1234, 5678};
    char* dataPtr = (char*)&data;

    typedef boost::iostreams::basic_array_source<char> Device;
    boost::iostreams::stream_buffer<Device> buffer(dataPtr, sizeof(data));
    boost::archive::binary_iarchive archive(buffer, boost::archive::no_header);

    uint16_t word1, word2;
    archive >> word1 >> word2;
    std::cout << word1 << "," << word2 << std::endl;
    return 0;
}

с GCC 4.4.1 на AMD64, он выводит:

1234 5678

BOOST.Serialization очень мощный и знает, как сериализовать все основные типы, строки и даже контейнеров STL. Вы можете легко сделать ваши типы сериализировать. Смотрите документацию. Скрытый где-то в усилении. Прозрачные источники являются примером портативного двоичного архива, который знает, как выполнить правильное замену для эндианса вашего компьютера. Это может быть полезно для вас.

Если вам не нужна фантазия Boost.Serialization и рады прочитать двоичные данные в FREAD () - Тип моды, вы можете использовать Basic_array_Source в более простом способе:

#include <stdint.h>
#include <iostream>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>

int main()
{
    uint16_t data[] = {1234, 5678};
    char* dataPtr = (char*)&data;

    typedef boost::iostreams::basic_array_source<char> Device;
    boost::iostreams::stream<Device> stream(dataPtr, sizeof(data));

    uint16_t word1, word2;
    stream.read((char*)&word1, sizeof(word1));
    stream.read((char*)&word2, sizeof(word2));
    std::cout << word1 << "," << word2 << std::endl;

    return 0;
}

Я получаю тот же выход с этой программой.

28
ответ дан 28 November 2019 в 01:52
поделиться

Я не уверен, что вам нужно, но делает ли это то, что вы хотите?

char *mybuffer;
size_t length;
// allocate, fill, set length, as before

std::string data(mybuffer, length);
std::istringstream mb(data);
//use mb
5
ответ дан 28 November 2019 в 01:52
поделиться

Стандартный буфер потока имеет такую функциональность.
Создать поток. Получает его буфер, затем переопределяет его.

#include <sstream>
#include <iostream>
#include <algorithm>
#include <iterator>

int main()
{
    // Your imaginary buffer
    char    buffer[]    = "A large buffer we don't want to copy but use in a stream";

    // An ordinary stream.
    std::stringstream   str;

    // Get the streams buffer object. Reset the actual buffer being used.
    str.rdbuf()->pubsetbuf(buffer,sizeof(buffer));

    std::copy(std::istreambuf_iterator<char>(str),
              std::istreambuf_iterator<char>(),
              std::ostream_iterator<char>(std::cout)
             );
}
4
ответ дан 28 November 2019 в 01:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: