C # /. NET - Пользовательские форматы двоичных файлов - с чего начать? - PullRequest
6 голосов
/ 27 апреля 2009

Мне нужно иметь возможность хранить некоторые данные в пользовательском двоичном формате. Я никогда не проектировал свой собственный формат файла раньше. Это должен быть дружественный формат для путешествий между мирами C #, Java и Ruby / Perl / Python.

Для начала файл будет состоять из записей. Поле GUID и поле пакета JSON / YAML / XML. Я не уверен, что использовать в качестве разделителей. Запятая, табуляция или символ новой строки кажутся слишком хрупкими. Что делает Excel? или форматы OpenOffice до XML? Если вы используете ASCII-символы 0 или 1. Не знаете, с чего начать. Какие-нибудь статьи или книги по теме?

Этот формат файла может быть расширен позже, чтобы включить «раздел заголовка».

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

UPDATE:
Обработка «пакетов» может быть медленной, но навигация в формате файла невозможна. Так что я думаю, что XML не обсуждается.

Ответы [ 5 ]

7 голосов
/ 27 апреля 2009

Как насчет использования "буферов протокола"? Разработанный как эффективный, переносимый, совместимый с версией двоичный формат общего назначения, он предоставляет вам C ++, Java и Python в библиотеке Google , а также C #, Perl, Ruby и другие в портах сообщества * * 1005

Обратите внимание, что Guid не имеет определенного типа данных, но вы можете использовать его как сообщение с (по существу) byte[].

Обычно для работы .NET, я бы порекомендовал protobuf-net (но, как автор, я несколько предвзят), однако, если вы собираетесь использовать другие языки позже вы можете добиться большего успеха (в долгосрочной перспективе), используя Jon's dotnet-protobufs ; это даст вам знакомый API для разных платформ (где protobuf-net использует идиомы .NET).

3 голосов
/ 27 апреля 2009

ASCII-символы 0 или 1 занимают несколько битов (как и любой другой символ), поэтому, если вы храните его таким образом, ваш «двоичный» файл будет в несколько раз больше, чем должен быть. В текстовом файле нулей и единиц нет точно двоичного файла:)

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

Однако , если ваш основной интерес - мобильность, я рекомендую вообще не использовать двоичный формат. XML точно разработан для решения проблемы переносимости и совместимости. Это многословный и весомый формат файла, но это компромисс, который вы делаете, чтобы решить эти проблемы за вас. Если удобочитаемый формат находится вне таблицы, ответ Марка идти. Не нужно изобретать колесо переносимости!

2 голосов
/ 29 апреля 2015

Я попытаюсь добавить несколько общих советов для создания переносимого двоичного формата файла.

Обратите внимание, что изобретать двоичный формат файла означает документировать, как должны идти биты в нем и что они значат. Это не кодирование, а документация.

Теперь подсказки:

  1. Решите, что делать с endianess . Хороший и простой способ - решить это раз и навсегда. При использовании на обычном ПК (то есть x86) для сохранения конверсий (производительности) предпочтение должно быть отдано порядку байтов.

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

    • Начните с магии, чтобы иметь возможность распознавать ваш формат (строка ASCII поможет)
    • Добавить версию. Версия вашего формата файла не помешает добавить, и это позволит вам сделать обратную совместимость позже.
  3. Наконец, добавьте данные. Теперь формат данных будет конкретным, и он всегда будет основан на ваших точных потребностях. В основном, данные будут храниться в виде двоичного изображения некоторой структуры данных. Вам нужна структура данных.

Если вам нужен произвольный доступ к вашим данным по каким-либо показателям, B-Trees - это путь, а если вам просто нужно много чисел, чтобы написать их все, а затем прочитать их все "массив" сделает свое дело.

Кроме того, вы можете использовать TLV (тип-длина-значение) для прямой совместимости.

1 голос
/ 28 апреля 2009

Предположим, ваш формат:

    struct Format
    {
        struct Header // 1
        {
            byte a;
            bool b1, b2, b3, b4, b5, b6, b7, b8;
            string name;
        }
        struct Container // 1...*
        {
            MyTypeEnum Type;
            byte[] data;
        }
    }

    enum MyTypeEnum
    {
        Sound,
        Video,
        Image
    }

Тогда у меня будет последовательный файл с:


байт // a

байт // b

int // имя размера

char [] // name (размер которого указан выше, помните, что в .NET символ 16 бит)

int // MyTypeEnum type

int // размер данных

байт [] // данные (размер которых указан выше)


Затем вы можете повторить последние три строки столько раз, сколько хотите.

Для чтения вы используете BinaryReader, который поддерживает чтение байтов, целых чисел и серий байтов. Существует также BinaryWriter.

Кроме того, помните, что Microsoft .NET (таким образом, на компьютере с Windows / Intel) имеет младший порядок. Так же как и BinaryReader и BinaryWriter.

1 голос
/ 27 апреля 2009

Это зависит от того, какой тип данных вы будете записывать в двоичный файл и какова цель двоичного файла. Это объект класса или просто запись данных? Если это записи данных, я бы порекомендовал поместить их в формате XML. Таким образом, вы можете включить проверку схемы, чтобы убедиться, что файл соответствует вашим стандартам. В java и .NET есть инструменты для импорта и экспорта данных из / в формат xml.

...