Разбор байтового потока на структуру / класс

У меня есть поток байтов, который мне нужно проанализировать в структуру, и мне также нужно иметь возможность анализировать структуру обратно в поток байтов.

Ниже приведен пример того, что я хочу, где я использовал BitConverter для анализа значений. Я надеюсь, что есть более эффективный способ сделать это, потому что мои структуры ОГРОМНЫ!

ref struct TestStruct
{
    int TestInt;
    float TestFloat;
};

int main(array<System::String ^> ^args)
{
    // populating array - just for demo, it's really coming from a file
    array<unsigned char>^ arrBytes = gcnew array<unsigned char>(8);
    Array::Copy(BitConverter::GetBytes((int)1234), arrBytes, 4);
    Array::Copy(BitConverter::GetBytes((float)12.34), 0, arrBytes, 4, 4);

    // parsing to struct - I want help
    TestStruct^ myStruct = gcnew TestStruct();
    myStruct->TestInt = BitConverter::ToInt32(arrBytes, 0);
    myStruct->TestFloat = BitConverter::ToSingle(arrBytes, 4);

    String^ str = Console::ReadLine();
    return 0;
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
939
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Здесь - это объяснение сериализации в .NET.

Для общего C++ (не управляемого) посмотрите boost :: serialize

Как форматируется двоичный формат, уже определено. Это подводит меня к настраиваемой сериализации и возвращает ту же проблему. Несколько сотен строк с BitConverter, или есть способ получше?

rozon 25.11.2008 11:44

Вы упоминаете как C++, так и .net. Только для C++ вы должны иметь возможность делать что-то вроде

char buffer[sizeof(MYSTRUCT)];
memcopy((char*) &mystruct, buffer, sizeof(MYSTRUCT));

Для .net вы ДОЛЖНЫ использовать сериализацию, если вы хотите избежать сохранения каждого элемента отдельно - классы не гарантируются для сохранения в непрерывном блоке памяти. Это раздражает, но это одна из «особенностей» управляемого кода - вы должны позволить ему управлять этим за вас.

-Адам

Да! Если бы вы могли объяснить, как это сделать в NET с управляемыми типами ссылок.

rozon 25.11.2008 11:45

Вы не можете. Вы должны сохранить каждую позицию отдельно или использовать сериализацию.

Adam Davis 25.11.2008 11:54

Могу ли я с помощью сериализации определить, каким должен быть выходной двоичный формат, без сохранения каждого элемента отдельно / вручную?

rozon 25.11.2008 12:08
Ответ принят как подходящий

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

struct a {
    int i;
}

struct b {
    string name;
    struct a a;
}

Что вы делаете, так это пишете простой синтаксический анализатор, который ищет в источнике (возможно, в каком-то заголовочном файле) слово «структура», затем вы читаете имя структуры (любое значение между «структура» и «{»). Напишите это на выходе:

cout << "struct " << name << " * read_struct_" << name << " (stream in) {" << NL
    << "    struct " << name << " * result = malloc (sizeof(struct " << name << "));" NL
parseFields (headerStream);
cout << "    return result;" << NL << "}" << NL ; } 

Обратите внимание, что мой C++ немного ржавый, поэтому он, вероятно, не компилируется, но вы должны понять.

В parseFields вы читаете каждую строку и разделяете ее на две части: все, что находится перед последним пробелом (например, «int» в первом примере) и что-то между последним пробелом и и «;». В данном случае это будет «i». Теперь вы пишете на выход:

cout << "read_" << fieldType << "(in, &result->" << fieldName << ");" << NL;

Примечание. Вам нужно будет заменить все пробелы ub в типе поля на "_".

На выходе это выглядит так:

struct a * read_struct_a (stream in) {
   struct a * result = malloc(sizeof(struct a));
   read_int(in, &result->i);
   return result;
}

Это позволяет вам определить, как читать или записывать int где-нибудь еще (в служебном модуле).

Теперь у вас есть код, который считывает определения структуры из файла заголовка и создает новый код, который может считывать структуру из некоторого потока. Дублируйте это, чтобы записать структуру в поток. Скомпилируйте сгенерированный код, и все готово.

Вы также захотите написать модульные тесты, чтобы убедиться, что синтаксический анализ работает правильно :) Просто создайте структуру в памяти, используйте методы записи, чтобы сохранить ее где-нибудь и прочитать ее снова. Теперь две структуры должны быть идентичными. Вам нужно будет написать третий генератор кода для создания кода для сравнения двух структур.

Вам нужно будет объяснить это подробнее. Структуры идентичны исходному формату, и я не контролирую источник (или формат).

rozon 25.11.2008 11:50

Сериализация - это здорово, но в моем случае мне не нужны «дополнительные услуги», и мне все равно придется проделывать ту же работу, чтобы иметь полный контроль над битами. Думаю, для большинства это могло быть решением.

Дать г-ну Дигулле правильный ответ, так как он больше всего напоминает мое решение. Также спасибо мистеру Дэвису, который объяснил мне, что это нужно сделать ...

Другие вопросы по теме