我有下面的C代码,它应该将任意对象序列化为字符串,然后当然反序列化它。

public static string Pack(Message _message)
{
   BinaryFormatter formatter = new BinaryFormatter();

   MemoryStream original = new MemoryStream();
   MemoryStream outputStream = new MemoryStream();

   formatter.Serialize(original, _message);
   original.Seek(0, SeekOrigin.Begin);

   DeflateStream deflateStream = new DeflateStream(outputStream, CompressionMode.Compress);
   original.CopyTo(deflateStream);

   byte[] bytearray = outputStream.ToArray();

   UTF8Encoding encoder = new UTF8Encoding();
   string packed = encoder.GetString(bytearray);
   return packed;
}

public static Message Unpack(string _packed_message)
{
    UTF8Encoding encoder = new UTF8Encoding();
    byte[] bytearray = encoder.GetBytes(_packed_message);

    BinaryFormatter formatter = new BinaryFormatter();

    MemoryStream input = new MemoryStream(bytearray);
    MemoryStream decompressed = new MemoryStream();

    DeflateStream deflateStream = new DeflateStream(input, CompressionMode.Decompress);
    deflateStream.CopyTo(decompressed); // EXCEPTION

    decompressed.Seek(0, SeekOrigin.Begin);

    var message = (Message)formatter.Deserialize(decompressed); // EXCEPTION 2
    return message;
}

但问题是,无论何时运行代码,我都会遇到异常。使用上面的代码并调用它,如下所示,我接收到invaliddataexception:unknown块类型。流可能已损坏。在标记的// EXCEPTION行。
在寻找这个问题之后,我试图摆脱通货紧缩。这只是一个很小的变化:在Pack中,bytearray是从original.ToArray()创建的,在Unpack中,我Seek()input而不是decompressed并使用Deserialize(input)而不是decompressed。唯一改变的结果是:异常位置和主体不同,但它仍然发生。我收到序列化异常:对象“201326592”没有映射。在// EXCEPTION 2处。
我好像看不出有什么问题。也许这是整个系列化的想法…问题在于,以某种方式打包Message实例是必要的,因为这些对象保存在服务器和客户机应用程序之间传递的信息。(序列化逻辑位于两端都引用的.shared dll项目中,但是,现在,我只是先开发服务器端。)还必须告诉您,我只使用string输出,因为现在服务器和客户端之间的TCP连接是基于两端的字符串读写。所以无论如何,它必须降到弦的水平。
消息对象的外观如下:
[Serializable]
public class Message
{
    public MessageType type;
    public Client from;
    public Client to;
    public string content;
}

Client现在是一个空类,只有Serializable属性,没有属性或方法。)
这就是调用pack unpack的方式(从Main()..):
 Shared.Message msg = Shared.MessageFactory.Build(Shared.MessageType.DEFAULT, new Shared.Client(), new Shared.Client(), "foobar");

 string message1 = Shared.MessageFactory.Pack(msg);
 Console.WriteLine(message1);

 Shared.Message mess2 = Shared.MessageFactory.Unpack(message1); // Step into... here be exceptions
 Console.Write(mess2.content);

这是一张显示ide中发生的事情的图片。控制台窗口中的输出是message1的值。
不幸的是,一些调查还显示问题可能存在于bytearray变量周围。当运行Pack()时,在编码器创建字符串后,数组包含152个值,但是在Unpack()中解码后,数组有160个值。
我很感激你的帮助,因为我真的没有主意了,有了这个问题,进步就成了障碍。谢谢您。
(更新)最终解决方案:
我要感谢大家的回答和评论,因为我已经达成了解决方案。谢谢您。
Marc Gravell是对的,我错过了deflateStream的关闭,因此,结果要么是空的,要么是损坏的。我花了我的时间,重新思考和重写了方法,现在它工作得完美无瑕。甚至通过网络流发送这些字节的目的也在起作用。
此外,正如Eric J.所建议的,当数据在ASCIIEnconding中流动时,我已经切换到使用string来进行byte[]Stream之间的更改。
固定代码如下:
public static string Pack(Message _message)
{
    using (MemoryStream input = new MemoryStream())
    {
       BinaryFormatter bformatter = new BinaryFormatter();
       bformatter.Serialize(input, _message);
       input.Seek(0, SeekOrigin.Begin);

       using (MemoryStream output = new MemoryStream())
       using (DeflateStream deflateStream = new DeflateStream(output, CompressionMode.Compress))
       {
           input.CopyTo(deflateStream);
           deflateStream.Close();

           return Convert.ToBase64String(output.ToArray());
       }
    }
}

public static Message Unpack(string _packed)
{
    using (MemoryStream input = new MemoryStream(Convert.FromBase64String(_packed)))
    using (DeflateStream deflateStream = new DeflateStream(input, CompressionMode.Decompress))
    using (MemoryStream output = new MemoryStream())
    {
        deflateStream.CopyTo(output);
        deflateStream.Close();
        output.Seek(0, SeekOrigin.Begin);

        BinaryFormatter bformatter = new BinaryFormatter();
        Message message = (Message)bformatter.Deserialize(output);
        return message;
    }
}

现在一切都发生得很好,如下面的截图所示。这是最初的预期产出。服务器和客户端可执行文件相互通信,消息传播…它被正确地序列化和非序列化。

最佳答案

除了现有的关于编码与BASE-64的观察,请注意,你还没有关闭通缩流。这很重要,因为压缩流缓冲区:如果不关闭,它可能不会写入结束。对于一个短流,这可能意味着它什么都不写。

using(DeflateStream deflateStream = new DeflateStream(
    outputStream, CompressionMode.Compress))
{
    original.CopyTo(deflateStream);
}
return Convert.ToBase64String(outputStream.GetBuffer(), 0,
    (int)outputStream.Length);

09-04 05:38