c # сериализация ascii путаница - PullRequest
4 голосов
/ 19 июня 2011

Вот код.

[Serializable]
public class HostedGame
{
    public int ID { get; set; }

    public int UID { get; set; }

    public String Name { get; set; }

    public Boolean Available { get; set; }

    public String Description { get; set; }

    public List<int> Users { get; set; }

    public int Port { get; set; }

    public HostedGame(int uid, String name, String description, int port)
    {
        UID = uid;
        Name = name;
        Description = description;
        Available = true;
        Port = port;
        Users = new List<int>();
    }

    public int CompareTo(Object obj)
    {
        int result = 1;
        if(obj != null && obj is HostedGame)
        {
            HostedGame w = obj as HostedGame;
            result = this.ID.CompareTo(w.ID);
        }
        return result;
    }

    static public int Compare(HostedGame x, HostedGame y)
    {
        int result = 1;
        if(x != null && y != null)
        {
            result = x.CompareTo(y);
        }
        return result;
    }

    public static HostedGame DeSerialize(byte[] data)
    {
        MemoryStream ms = new MemoryStream(data);
        BinaryFormatter bff = new BinaryFormatter();
        return (HostedGame)bff.Deserialize(ms);
    }

    public static byte[] Serialize(HostedGame obj)
    {
        BinaryFormatter bff = new BinaryFormatter();
        MemoryStream ms = new MemoryStream();
        bff.Serialize(ms, obj);
        return ms.ToArray();
    }
}

Код ниже не работает правильно:

HostedGame hs = new HostedGame(12,"Name", "Description", 8088);
String s = Encoding.ASCII.GetString(HostedGame.Serialize(hs));
HostedGame HACK = HostedGame.DeSerialize(Encoding.ASCII.GetBytes(s));

HACK.Port почему-то получается 7999?

Когда я просто делаю это ...

HostedGame HACK = HostedGame.DeSerialize(HostedGame.Serialize(hs));

Работает нормально.

Итак, я спрашиваю:

  1. Почему я получаю неправильное значение?
  2. Есть ли лучший способ преобразовать байты в строку и обратно?

Ответы [ 2 ]

9 голосов
/ 19 июня 2011

Вы не можете использовать Encoding.ASCII.GetString для преобразования любого байтового массива в строку. Вы теряете некоторые данные, когда вы делаете это. Вместо этого используйте Convert.ToBase64String. Этот будет составлять строку из любой последовательности байтов без потери данных.

HostedGame hs = new HostedGame(12,"Name", "Description", 8088);
String s = Convert.ToBase64String(HostedGame.Serialize(hs));
HostedGame HACK= HostedGame.DeSerialize(Convert.FromBase64String(s));

Вот пример, который показывает, как при использовании Encoding.ASCII данные теряются.

var testBytes = new byte[] { 250, 251, 252 };
var text = Encoding.ASCII.GetString(testBytes);
var bytes = Encoding.ASCII.GetBytes(result); // will be 63, 63, 63
3 голосов
/ 19 июня 2011

Двоичная сериализация генерирует байтовый массив, который не является (обязательно) допустимой строкой в ​​любой кодировке.

Когда вы пытаетесь прочитать его как текст ASCII, декодер ASCII преобразует любые недопустимые байты (> 128) в ? символы.
Поэтому, когда вы возвращаете его обратно в байты ASCII, вы получаете другой набор байтов.

Короче говоря, не обрабатывает двоичные данные как ASCII или как любую другую кодировку текста.

Если вам нужно отправить двоичные данные в виде простого текста, используйте Base64 для безопасного преобразования их в текст.

...