C#序列化ASCII混淆

4
这是代码。
[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

使用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

请解释一下,什么使得那是一个更好的选择? - Kelly Elton
4
这并不是更好的选择,而是可行的选择。你的选择不可行,所以它隐含着更好的选择 :) - Marino Šimić

3

二进制序列化生成一个字节数组,这个数组在任何编码下都不一定是有效的字符串。

当您尝试将其作为ASCII文本读取时,ASCII解码器会将任何无效的字节(> 128)转换为?字符。
因此,当您将其转换回ASCII字节时,您最终得到的是一组不同的字节。

简而言之,不要将二进制数据视为ASCII文本或其他文本编码

如果您需要将二进制数据作为纯文本发送,请使用Base64将其安全地转换为文本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接