Почему я не могу прочитать поле VarInt из двоичных данных с помощью protobuf-net - PullRequest
1 голос
/ 19 декабря 2011

каждый,

Я использую библиотеку protobuf-net для сериализации-десериализации текстовых данных в двоичные файлы.В прошлом у меня была похожая ошибка, но потом я сделал ошибку, записав двоичные данные в текстовый файл.На этот раз я уверен, что файл написан в двоичном режиме.В то время как я читаю данные, я получаю Исключение EndOfStream: попытка чтения после конца потока.

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

message HeaderMessage {
  required double timestamp = 1;
  required string ric_code = 2;
  required int32 count = 3;
  required int32 total_message_size = 4;
}

Я получаю исключение, когда читаю поле total_message_size в фиксированном местоположении

HEADER: 1111    1       1       hk      0
File: 398909440 bytes
Reading data objects:
1073561: 09 e3 a5 9b c4 0c b3 e0 40 12 07 31 30 39 33 2e 48 4b 18 04 20 5a
1073677: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 32 39 37 2e 48 4b 18 02 20 2d
1073748: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 32 39 37 2e 48 4b 18 04 20 5a
1073864: 09 e3 a5 9b c4 0c b3 e0 40 12 07 38 31 37 33 2e 48 4b 18 02 20 2d
1073935: 09 e3 a5 9b c4 0c b3 e0 40 12 07 38 31 37 33 2e 48 4b 18 04 20 5b
1074052: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 32 33 35 2e 48 4b 18 02 20 2d
1074123: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 36 30 33 2e 48 4b 18 02 20 2d
1074194: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 36 30 33 2e 48 4b 18 04 20 5b
1074311: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 32 33 35 2e 48 4b 18 06 20 8a

В приведенном выше выводе первое поле - это позиция потока.Общая длина потока составляет 398909440. Поэтому невозможно, чтобы поток достиг своего конца.Я попытался напечатать отдельные поля в тот момент, когда он не может прочитать, я вижу, что класс ProtoReader всегда не может прочитать поле total_message_size.

В выходных данных aboe последняя строка является виновником, когда protobuf-net не может прочитать данные.

1074311: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 32 33 35 2e 48 4b 18 06 20 8a

Если мы разбиваем поля, данные выглядят следующим образом:

field1 timestamp field: type: 09  payload: e3 a5 9b c4 0c b3 e0 40
field2 ric_code field: type: 12   payload: 07 30 32 33 35 2e 48 4b
field3 count field:    type: 18   payload: 06
field4 total_message_size: type: 20 payload: 8a

исключение возникает при чтении полезной нагрузки 4-го поля, и значение равно 8a.(десятичное 138).

Трассировка стека выглядит следующим образом:

   at ProtoBuf.ProtoReader.TryReadUInt32VariantWithoutMoving(Boolean trimNegative, UInt32& value) in C:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 101
   at ProtoBuf.ProtoReader.ReadUInt32Variant(Boolean trimNegative) in C:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 138
   at ProtoBuf.ProtoReader.ReadInt32() in C:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 264
   at protobuf_test.Program.Main(String[] args) in H:\Personal\Visual Studio 2010\Projects\protobuf-test\protobuf-test\Program.cs:line 80
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

В чем проблема при чтении значения 138?В чем проблема в этом случае?

С уважением, Alok

1 Ответ

2 голосов
/ 19 декабря 2011

0x8a является , а не допустимым вариантом.Кодирование Varint использует MSB в качестве бита продолжения, что означает: если MSB установлен, ожидается, по крайней мере, еще один байт (он продолжается до тех пор, пока MSB не будет установлен , а не , объединяя оставшиеся 7-битные порции немногопо-индийски)Следовательно, 0x8a не может существовать само по себе в действительном варианте.0x8a и что-то еще , обязательно .Это можно увидеть в спецификации wire .Пожалуйста, убедитесь, что вы случайно не обрезали конец этого отдельного сообщения или не указали длину (поскольку я понимаю, что каждая запись индивидуально завернута с префиксом размера).

...