Лучший способ сериализации структуры C для десериализации с помощью Java и т. Д. - PullRequest
6 голосов
/ 18 марта 2009

В настоящее время я сохраняю и загружаю некоторые данные в структурах C / C ++ в файлы с помощью fread () / fwrite (). Это прекрасно работает при работе в этом приложении C (я могу перекомпилировать всякий раз, когда структура меняется, чтобы обновить аргументы sizeof () для fread () / fwrite ()), но как я могу загрузить этот файл в других программах, не зная заранее sizeof () с структуры C?

В частности, я написал это другое Java-приложение, которое визуализирует данные, содержащиеся в этом двоичном файле структуры C, но я хотел бы получить общее решение о том, как читать этот двоичный файл. (Вместо того, чтобы мне приходилось вручную добавлять sizeof () в исходный код приложения Java при каждом изменении структуры C ...)

Я думаю о сериализации в какой-то текст или XML, но я не уверен, с чего начать (как сериализовать в C, затем как десериализовать в Java и, возможно, других языках в будущем), и если это целесообразно, то здесь, где один из членов структуры является массивом с плавающей запятой, который может быть увеличен до ~ 50 МБ в двоичном формате (и у меня есть сотни этих файлов данных для чтения и записи).

Структура C проста (без серьезных вложений или указателей) и выглядит следующим образом:

struct MyStructure {
    char *title;
    int id;
    int param1;
    int param2;
    float *data;
}

Части, которые могут измениться больше всего, являются целыми числами параметров.

Какие у меня есть варианты?

Ответы [ 8 ]

4 голосов
/ 18 марта 2009

Если вы контролируете обе базы кода, вам следует рассмотреть возможность использования Буферы протокола .

4 голосов
/ 18 марта 2009

Вы можете использовать формат Java DataInput / DataOutput, который хорошо описан в javadoc .

3 голосов
/ 19 марта 2009

Посмотрите на JSON. http://www.json.org. Если вы переходите от JavaScript, это большая помощь. Я не знаю, насколько хороша поддержка Java.

1 голос
/ 18 марта 2009

Взгляните на Услуги Ресина по гессенской / мешковине . Возможно, вам не нужен весь сервис, только часть API и понимание проводного протокола.

1 голос
/ 18 марта 2009

Если ваша структура не изменится (сильно), и ваши данные будут в довольно непротиворечивом формате, вы можете просто записать значения в файл CSV или в другой простой формат.

Это легко читается на Java, и вам не придется беспокоиться о сериализации в XML. Иногда идти проще - самый простой маршрут.

0 голосов
/ 19 марта 2009

Если:

  • ваши данные представляют собой большой массив с плавающей точкой;
  • вы можете протестировать процедуру записи / чтения во всех вероятных средах (= комбинации машин / компилятора ОС / C), на которых будет работать каждый конец;
  • производительность важна.

тогда я, вероятно, просто продолжал бы записывать данные из C так, как вы это делаете (возможно, с небольшой поправкой - см. Ниже), и превратил бы проблему в способ чтения этих данных из Java.

Чтобы прочитать данные обратно из Java, используйте ByteBuffer . По сути, извлекайте куски байтов из ваших данных, оборачивайте их байтовым буфером, а затем используйте методы get (), getFloat (), getInt () и т. Д. Пакет NIO также имеет буферы «обертки», например, FloatBuffer, который из проведенных мною тестов выглядит примерно на 20% быстрее для чтения больших чисел одного типа.

Теперь, одна вещь, с которой вам нужно быть осторожным, это порядок байтов. Из Java вам нужно вызвать order (ByteOrder.LITTLE _ ENDIAN) или order (ByteOrder.BIG _ ENDIAN) в вашем буфере, прежде чем вы начнете читать данные. Чтобы решить, какой из них использовать, я бы порекомендовал в самом начале потока записать известное 16-байтовое значение (например, 255 = 0x00ff). Затем из Java вытащите эти два байта и проверьте порядок (0xff, 0x00 или 0x00, 0xff), чтобы увидеть, есть ли у вас маленький или большой порядок байтов.

0 голосов
/ 18 марта 2009

Мне нравятся ответы CSV и "Protocol Buffers" (хотя, на первый взгляд, буфер протокола может быть очень похож на YAML, насколько я знаю).

Если вам нужны плотно упакованные записи для больших объемов данных, вы можете рассмотреть это:

Создание текстового заголовка файла, описывающего текущую структуру файла: размеры записи (типы ????) и имена / размеры полей. Прочитайте и проанализируйте заголовок, а затем используйте низкоуровневые операции двоичного ввода-вывода, чтобы загрузить поля каждой записи, то есть свойства объекта или как мы его называем в этом году.

Это дает вам возможность немного изменить структуру и сделать ее самоописываемой, в то же время позволяя упаковать большой объем в меньшем пространстве, чем XML.

TMTOWTDI, наверное.

0 голосов
/ 18 марта 2009

Одной из возможностей является создание небольших файлов XML с заголовком, идентификатором, параметрами и т. Д., А затем ссылка (по имени файла) на место, где содержатся данные с плавающей точкой. Предполагая, что в данных с плавающей запятой нет ничего особенного, и что Java и C используют один и тот же формат с плавающей запятой, вы можете прочитать этот файл с помощью readFloat () из DataInputStream .

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