Запись структуры в stringstream на языке C++


У меня есть такие структуры, как:

struct dHeader
{
    uint8_t    blockID;
    uint32_t   blockLen;
    uint32_t   bodyNum;
};
struct dBody
{
    char       namestr[10];
    uint8_t    blk_version;
    uint32_t   reserved1;
}

И у меня есть stringstream как:

std::stringstream Buffer(std::iostream::in | std::iostream::out);

Я хочу записать dHdr и несколько структур dBody в буфер с помощью

Buffer << Hdr1;
Buffer << Body1;
Buffer << Body1;

Я получаю ошибку:

Ошибка: нет соответствия для 'operator

Если я попробую с:

Buffer.write(reinterpret_cast<char*>(&Hdr1), sizeof(dbHdr1));
Buffer.write(reinterpret_cast<char*>(&Body1), sizeof(Body1));
Buffer.write(reinterpret_cast<char*>(&Body2), sizeof(Body2));

Я путаюсь в упаковке и выравнивании памяти.

  • как лучше всего записать структуру в поток строк?
  • и еще читать струнный поток в обычную строку?
2   2  

2 ответа:

Для каждой из ваших структур вам нужно определить что-то подобное этому:

struct dHeader
{
    uint8_t    blockID;
    uint32_t   blockLen;
    uint32_t   bodyNum;
};

std::ostream& operator<<(std::ostream& out, const dHeader& h)
{
     return out << h.blockID << " " << h.blockLen << " " << h.bodyNum;
}

std::istream& operator>>(std::istream& in, dHeader& h) // non-const h
{
    dHeader values; // use extra instance, for setting result transactionally
    bool read_ok = (in >> values.blockID >> values.blockLen >> values.bodyNum);

    if(read_ok /* todo: add here any validation of data in values */)
        h = std::move(values);
    /* note: this part is only necessary if you add extra validation above
    else
        in.setstate(std::ios_base::failbit); */
    return in;
}

(аналогично для других структур).

Редактировать: являются небуферизованные модули чтения/записи реализация имеет следующие недостатки:

  • Он неформатирован; это не может быть проблемой для небольшого служебного приложения, если вы контролируете, где оно компилируется и запускается, но обычно, если вы берете сериализованные данные и запускаете / компилируете приложение на другой архитектуре, у вас будут проблемы с endianness; вам также нужно будет убедиться, что типы, которые вы используете, не зависят от архитектуры (т. е. продолжайте использовать типы uintXX_t).

  • Он хрупок; реализация зависит от структур, содержащих только типы POD. Если вы добавите символ* в свою структуру позже, ваш код будет компилироваться таким же образом, только с неопределенным поведением.

  • Это неясно (клиенты вашего кода ожидали бы либо увидеть интерфейс, определенный для ввода-вывода, либо предположить, что ваши структуры поддерживают нет сериализации). Обычно никто не думает: "может быть, я могу сериализовать, но используя небуферизованный ввод-вывод" - по крайней мере, не будучи клиентом пользовательской реализации структуры или класса.

Проблемыможно улучшить, добавив операторы потока ввода-вывода, реализованные в терминах небуферизованных операций чтения и записи.

Пример кода для операторов выше:

std::ostream& operator<<(std::ostream& out, const dHeader& h)
{
     out.write(reinterpret_cast<char*>(&h), sizeof(dHeader));
     return out;
}

std::istream& operator>>(std::istream& in, dHeader& h) // non-const h
{
    dHeader values; // use extra instance, for setting result transactionally
    bool read_ok = in.read( reinterpret_cast<char*>(&values), sizeof(dHeader) );

    if(read_ok /* todo: add here any validation of data in values */)
        h = std::move(values);
    /* note: this part is only necessary if you add extra validation above
    else
        in.setstate(std::ios_base::failbit); */
    return in;
}

Это централизует код за интерфейсом (т. е. если ваш класс больше не поддерживает без буферизации записи, вам придется изменить код в одном месте), и делает ваше намерение очевидным (реализация сериализации для вашей структуры). Она все еще хрупкая, но уже не такая.

Вы можете обеспечить перегрузку для std::ostream::operator<<, как

std::ostream& operator<<(std::ostream&, const dHeader&);
std::ostream& operator<<(std::ostream&, const dBody&);

Дополнительную информацию смотрите в этом вопросеstackoverflow .