【问题标题】:Serializing/deserializing with memory stream使用内存流进行序列化/反序列化
【发布时间】:2012-05-10 13:07:03
【问题描述】:

我在使用内存流进行序列化时遇到问题。这是我的代码:

/// <summary>
/// serializes the given object into memory stream
/// </summary>
/// <param name="objectType">the object to be serialized</param>
/// <returns>The serialized object as memory stream</returns>
public static MemoryStream SerializeToStream(object objectType)
{
    MemoryStream stream = new MemoryStream();
    IFormatter formatter = new BinaryFormatter();
    formatter.Serialize(stream, objectType);
    return stream;
}

/// <summary>
/// deserializes as an object
/// </summary>
/// <param name="stream">the stream to deserialize</param>
/// <returns>the deserialized object</returns>
public static object DeserializeFromStream(MemoryStream stream)
{
    IFormatter formatter = new BinaryFormatter();
    stream.Seek(0, SeekOrigin.Begin);
    object objectType = formatter.Deserialize(stream);
    return objectType;
} 

我得到的错误如下: 流不是有效的二进制格式。起始内容(以字节为单位)是:blah....

我不确定是什么导致了错误。任何帮助将不胜感激。

调用示例:

Dog myDog = new Dog();
myDog.Name= "Foo";
myDog.Color = DogColor.Brown;

MemoryStream stream = SerializeToStream(myDog)

Dog newDog = (Dog)DeserializeFromStream(stream);

【问题讨论】:

  • 提供您用来调用方法的代码。
  • 你能告诉我们你是如何使用这个代码的吗?怀疑这个参数命名为objectType
  • 执行您的代码示例没有任何问题。你还有其他处理流对象的部分吗?
  • 这里一样,代码有效。你能展示你的 Dog 课程吗?那 DogColor 类型是什么?

标签: c# serialization deserialization memorystream


【解决方案1】:

这段代码对我有用:

public void Run()
{
    Dog myDog = new Dog();
    myDog.Name= "Foo";
    myDog.Color = DogColor.Brown;

    System.Console.WriteLine("{0}", myDog.ToString());

    MemoryStream stream = SerializeToStream(myDog);

    Dog newDog = (Dog)DeserializeFromStream(stream);

    System.Console.WriteLine("{0}", newDog.ToString());
}

类型是这样的:

[Serializable]
public enum DogColor
{
    Brown,
    Black,
    Mottled
}

[Serializable]
public class Dog
{
    public String Name
    {
        get; set;
    }

    public DogColor Color
    {
        get;set;
    }

    public override String ToString()
    {
        return String.Format("Dog: {0}/{1}", Name, Color);
    }
}

实用方法有:

public static MemoryStream SerializeToStream(object o)
{
    MemoryStream stream = new MemoryStream();
    IFormatter formatter = new BinaryFormatter();
    formatter.Serialize(stream, o);
    return stream;
}

public static object DeserializeFromStream(MemoryStream stream)
{
    IFormatter formatter = new BinaryFormatter();
    stream.Seek(0, SeekOrigin.Begin);
    object o = formatter.Deserialize(stream);
    return o;
}

【讨论】:

  • 我实现了您现在建议的代码并且代码抛出了这个异常:异常已被调用的目标抛出。它发生在行对象 o = formatter.Deserialize(stream);我做错了什么?
  • 好吧,我在反序列化构造函数中犯了一个可怕的错误。我的一个属性的信息是错误的(即... = info.GetValue("HereWasWrong_ItWasNonExistingThing", typeof(int));) 这是这个工作的一个很好的链接,有人可能需要它:codeproject.com/Articles/1789/Object-Serialization-using-C 也谢谢对 Cheeso 来说,答案很好。
  • BinaryFormatter 序列化已过时,不应使用。请参阅aka.ms/binaryformatter 了解更多信息。
【解决方案2】:

使用方法从内存中序列化和反序列化集合对象。这适用于集合数据类型。此方法会将任何类型的集合序列化为字节流。创建一个单独的类SerilizeDeserialize并添加以下两个方法:

public class SerilizeDeserialize
{

    // Serialize collection of any type to a byte stream

    public static byte[] Serialize<T>(T obj)
    {
        using (MemoryStream memStream = new MemoryStream())
        {
            BinaryFormatter binSerializer = new BinaryFormatter();
            binSerializer.Serialize(memStream, obj);
            return memStream.ToArray();
        }
    }

    // DSerialize collection of any type to a byte stream

    public static T Deserialize<T>(byte[] serializedObj)
    {
        T obj = default(T);
        using (MemoryStream memStream = new MemoryStream(serializedObj))
        {
            BinaryFormatter binSerializer = new BinaryFormatter();
            obj = (T)binSerializer.Deserialize(memStream);
        }
        return obj;
    }

}

如何在你的类中使用这些方法:

ArrayList arrayListMem = new ArrayList() { "One", "Two", "Three", "Four", "Five", "Six", "Seven" };
Console.WriteLine("Serializing to Memory : arrayListMem");
byte[] stream = SerilizeDeserialize.Serialize(arrayListMem);

ArrayList arrayListMemDes = new ArrayList();

arrayListMemDes = SerilizeDeserialize.Deserialize<ArrayList>(stream);

Console.WriteLine("DSerializing From Memory : arrayListMemDes");
foreach (var item in arrayListMemDes)
{
    Console.WriteLine(item);
}

【讨论】:

  • 您可以使用此代码将对象序列化到字节流或从字节流中序列化,以存储在隔离存储或远程存储中。借助此功能,您可以在应用程序会话之间保持集合。
  • 谢谢你。为什么大家都说不能序列化匿名类型呢?
【解决方案3】:

BinaryFormatter 在某些特定情况下可能会产生无效输出。例如,它将省略未配对的代理字符。接口类型的值也可能存在问题。阅读此documentation page,包括社区内容。

如果您发现错误持续存在,您可能需要考虑使用 XML 序列化程序,例如 DataContractSerializerXmlSerializer

【讨论】:

    【解决方案4】:

    在 .Net 6 中使用 System.Text.Json 可以轻松完成 使用 System.Text.Json;

    Examlple ex = JsonSerializer.Deserialize<Example>(ms);
    Console.WriteLine(ex.Value);
    
    class Example
    {
        string Value {get; set; }
    }
    

    序列化参考this

    【讨论】:

    • 这仅从 .Net6 开始有效
    • @g0np 感谢您指出这一点。我在回答中提到了 .Net 6 版本。
    猜你喜欢
    • 1970-01-01
    • 2021-12-13
    • 2021-05-08
    • 2017-12-26
    • 1970-01-01
    • 2011-12-30
    • 2021-12-30
    • 1970-01-01
    • 2016-03-02
    相关资源
    最近更新 更多