2011-12-19 1 views
1

всех,Почему я не может прочитать поле VarInt из двоичных данных с использованием Protobuf-сетью

Я использую Protobuf-сеть библиотеку для сериализации-десериализация текстовых данных в бинарные файлы. У меня была аналогичная ошибка в прошлом, но затем я ошибся в записи двоичных данных в текстовый файл. На этот раз я уверен, что файл записан в двоичном режиме. Пока я читаю данные, получаю Исключение 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-го поля и значение 8а. (десятичное значение 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

+0

Благодарим вас за то, что вы указали достаточно информации, чтобы дать ответ, но это, похоже, проблема с * writer * (который IIRC - это C++ в вашем случае), а не * reader * (protobuf-net) –

ответ

1

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

+0

Thanks Марк. Я писал неправильную длину заголовка при записи длины заголовка. В основном я помещаю заголовок в двоичные данные, а затем перед записью фактического сообщения заголовка я обновил одно из значений заголовка, которое должно было изменить длину заголовка. – Alok

Смежные вопросы