десериализация "длинной" строки с помощью protobuf для c # не работает для меня должным образом - PullRequest
4 голосов
/ 15 октября 2011

Я, очевидно, делаю что-то не так, но не могу понять это и не могу найти документацию.

Я экспериментирую с proto-buf для .NET от Marc Gravell и пытаюсьСериализация и десериализация объектов.Как только объект содержит строку, которая является «слишком длинной» (не пытался точно определить порог размера, но он составляет несколько сотен байтов), строка не десериализуется должным образом для меня.

Это мой код:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using ProtoBuf;

namespace ConsoleApplication1
{
public class Program
{
    [ProtoContract]
    public class test
    {
        [ProtoMember(1)]            
        public int i;
        [ProtoMember(2)]
        public string s1;
        [ProtoMember(3)]
        public string s2;
        [ProtoMember(4)]
        public char[] arrchars;
        [ProtoMember(5)]
        public Dictionary<int, string> Dict = new Dictionary<int, string>();

    }


    static void Main(string[] args)
    {
        test var1 = new test();
        var1.i = 10;
        var1.s1 = "Hello";
        var1.arrchars = new char[] {'A', 'B', 'C'};
        var1.Dict.Add(10, "ten");
        var1.Dict.Add(5, "five");
        var1.s2 = new String('X', 520);

        string s = PBSerializer.Serialize(typeof (test), var1);

        test var2 = null;
        PBSerializer.Deserialize(s, out var2);
    }


    public static class PBSerializer
    {
        public static string Serialize(Type objType, object obj)
        {
            MemoryStream stream = new MemoryStream();
            ProtoBuf.Serializer.Serialize(stream, obj);
            // ProtoBuf.Serializer.SerializeWithLengthPrefix(stream, obj, PrefixStyle.Fixed32, 1);
            stream.Flush();
            stream.Position = 0;
            StreamReader sr = new StreamReader(stream);
            string res = sr.ReadToEnd();
            stream.Dispose();
            sr.Dispose();
            return res;
        }

        public static void Deserialize(string serializedObj, out test obj)
        {
            MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(serializedObj));
            obj = ProtoBuf.Serializer.Deserialize<test>(stream);
            // obj = ProtoBuf.Serializer.DeserializeWithLengthPrefix<test>(stream, PrefixStyle.Fixed32, 1);
            stream.Dispose();
        }

    }

}
}

var2.s2 не идентичен var1.s2 - он имеет дополнительный символ в начале строки и усекает большую часть конца строки.Однако, если я изменю длину var1.s2 на небольшое число (скажем, 52 вместо 520 символов), моя проблема исчезнет, ​​но мне нужно иметь возможность сериализовать длинные строки.Я предполагаю, что это связано с тем, что я делаю неправильно с настройкой PrefixStyle (?) Или, возможно, я не использую правильную кодировку (?).Однако метод проб и ошибок не помог мне разобраться.

Я использую .NET 3.5 и попробовал его с версиями 444 и 450 с тем же результатом.

Спасибо.

1 Ответ

8 голосов
/ 15 октября 2011

Вы сериализуете двоичные данные - но затем пытаетесь прочитать их, как если бы они были текстовыми. Это не так - не делай этого.

Если у вас есть для преобразования произвольных двоичных данных в текст, используйте Convert.ToBase64String и Convert.FromBase64String.

public static class PBSerializer
{
    public static string Serialize(Type objType, object obj)
    {
        using (MemoryStream stream = new MemoryStream())
        {
            ProtoBuf.Serializer.Serialize(stream, obj);
            return Convert.ToBase64String(stream.ToArray());
        }
    }

    // Ideally change this to use a return value instead of an out parameter...
    public static void Deserialize(string serializedObj, out test obj)
    {
        byte[] data = Convert.FromBase64String(serializedObj);
        using (MemoryStream stream = new MemoryStream(data))
        {
            obj = ProtoBuf.Serializer.Deserialize<test>(stream);
        }
    }
...