Whi*_*ity 7 c# encoding serialization object stream
我有以下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;
}
Run Code Online (Sandbox Code Playgroud)
但问题是,无论何时运行代码,我都会遇到异常.使用上面的代码并调用它,如下所示,我收到InvalidDataException:未知的块类型.流可能已损坏.在标记的// EXCEPTION行.
在寻找这个问题之后,我试图放弃通缩.这只是一个很小的改变:in Pack,bytearrayfrom original.ToArray()和in in Unpack,我Seek() input代替decompressed和使用Deserialize(input)而不是decompressed.唯一改变的结果是:异常位置和身体是不同的,但它仍然发生.我收到一个SerializationException:没有对象'201326592'的映射.在// EXCEPTION 2.
我似乎没有看到什么问题.也许这是整个序列化的想法...问题是,不知何故管理到包装的Message情况下是必要的,因为这些对象保存在服务器和客户端应用程序之间传输的信息.(序列化逻辑在一个.Shared DLL项目中,在两端引用,但是,现在,我只是首先开发服务器端.)还必须告诉我,我现在只使用string输出,服务器和客户端之间的TCP连接基于端部的字符串读写.所以不得不将它降低到字符串的水平.
这是Message对象的样子:
[Serializable]
public class Message
{
public MessageType type;
public Client from;
public Client to;
public string content;
}
Run Code Online (Sandbox Code Playgroud)
(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);
Run Code Online (Sandbox Code Playgroud)
这是一个显示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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在一切都恰到好处,如下面的截图所示.这是第一名的预期产出.在服务器和客户端可执行文件相互沟通和信息传播......它被序列化,妥善系列化.

除了有关Encoding vs base-64的现有观察之外,请注意您尚未关闭deflate流.这很重要,因为压缩流缓冲:如果你不关闭,它可能不会写结束.对于短流,这可能意味着它什么都没写.
using(DeflateStream deflateStream = new DeflateStream(
outputStream, CompressionMode.Compress))
{
original.CopyTo(deflateStream);
}
return Convert.ToBase64String(outputStream.GetBuffer(), 0,
(int)outputStream.Length);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4007 次 |
| 最近记录: |