Вы не можете сделать это с 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 байта в нашем резервном буфере (выборка больше, если мы хотим)
- мы увеличиваем некоторые счетчики, чтобы мы могли отслеживать нашу позицию в логическом буфере
- читаем данные из буфера
Если у вас есть ридер для вашего формата, десериализация должна быть намного проще.