Можно ли использовать сериализацию C # для чтения двоичного файла в произвольном формате? - PullRequest
4 голосов
/ 11 ноября 2010

У меня есть собственный двоичный файл, который я хочу прочитать в своей программе на C #.

Существует несколько различных форматов, сначала MSB, сначала LSB, а некоторые с переменными в разных порядках.

В настоящее время у меня есть класс, который читает правильное количество байтов, по одному за раз.

Это очень медленно, и поэтому я стремлюсь улучшить производительность любым возможным способом.

* 1008Может ли сериализация работать лучше?Если это так, возможно ли это в сценарии, который я описал?Можно ли настроить двоичный формат для формата big / little-endian?

Спасибо.

Ответы [ 2 ]

2 голосов
/ 11 ноября 2010

Вы не можете сделать это с BinaryFormatter - он будет ожидать дополнительные метаданные / заполнение вокруг объекта. Вы должны будете читать вручную либо из Stream, либо аналогично через двоичный считыватель.

Сделав какой-то очень похожий код, я бы написал свой собственный читатель, который находится поверх потока, с такими методами: ReadInt32LittleEndian, ReadInt32BigEndian (и т. Д. Для всего, что вам нужно) - и использовал shift (<<) / >>) для сборки байтов. Но важно Я бы использовал резервный буфер для уменьшения количества обращений к базовому потоку (даже с буфером это может быть недопустимо медленно).

Позвольте мне сослаться на некоторый код из protobuf-net, который делает это ... в частности ProtoReader, на примере:

    /// <summary>
    /// Reads an unsigned 32-bit integer from the stream; supported wire-types: Variant, Fixed32, Fixed64
    /// </summary>
    public uint ReadUInt32()
    {
        switch (wireType)
        {
            case WireType.Variant:
                return ReadUInt32Variant(false);
            case WireType.Fixed32:
                if (available < 4) Ensure(4, true);
                position += 4;
                available -= 4;
                return ((uint)ioBuffer[ioIndex++])
                    | (((uint)ioBuffer[ioIndex++]) << 8)
                    | (((uint)ioBuffer[ioIndex++]) << 16)
                    | (((uint)ioBuffer[ioIndex++]) << 24);
            case WireType.Fixed64:
                ulong val = ReadUInt64();
                checked { return (uint)val; }
            default:
                throw CreateException();
        }
    }

(здесь wireType в общем действует как индикатор порядка байтов и т. Д., Но это не важно)

Рассматривая реализацию Fixed32:

  • Ensure гарантирует, что у нас есть еще как минимум 4 байта в нашем резервном буфере (выборка больше, если мы хотим)
  • мы увеличиваем некоторые счетчики, чтобы мы могли отслеживать нашу позицию в логическом буфере
  • читаем данные из буфера

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

0 голосов
/ 11 ноября 2010

Нет, это не сработает. Ну, может, но издержки от преобразования, скорее всего, снизят производительность.

...