繁体   English   中英

在不使用文件系统的情况下,在 C# 中序列化和反序列化 object

[英]Serializing and Deserializing object in C# without using file system

我正在尝试将 object 保存为序列化字符串,然后我需要在稍后阶段将其反序列化回 object。 我想避免使用文件系统。

使用此 function 完成序列化:

  public string SerializeObject<T>(T objectToSerialize)
  {
    BinaryFormatter bf = new BinaryFormatter();
    MemoryStream memStr = new MemoryStream();
    try
    {
      bf.Serialize(memStr, objectToSerialize);
      memStr.Position = 0;
      return Convert.ToBase64String(memStr.ToArray());
    }
    finally
    {
      memStr.Close();
    }
  }

我从这里得到的。

这似乎工作。 但是,当我尝试使用以下函数反序列化为 object 时,出现错误。

  public Call deSerialize(string Serialized)
  {
    Stream Fs = GenerateStreamFromString(Serialized);
    BinaryFormatter F = new BinaryFormatter();
    Call s1 = (Call)F.Deserialize(Fs);
    Fs.Close();
    return s1;
  }

  public Stream GenerateStreamFromString(string s)
  {
    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    writer.Write(Convert.FromBase64String(s));
    writer.Flush();
    stream.Position = 0;
    return stream;
  }

我得到的错误是:

End of Stream encountered before parsing was completed.

它发生在以下行上:

Call s1 = (Call)F.Deserialize(Fs);

有没有办法解决这个问题,或者可能是在不使用文件系统的情况下反序列化字符串的更好方法?


免责声明:我一般不反对使用 Newtonsoft Json


问题是您正在使用StreamWriter将重构的字节从Convert.FromBase64String写入MemoryStream

MSDN:(我的重点)

实现一个TextWriter ,用于以特定编码将字符写入 stream。

在您的情况下,这会导致MemoryStream中的缓冲区更小,从而导致稍后在Deserialize中出现异常。

我们可以看到以下尺寸的差异:

MemStreamTest.exe Information: 0 : Position: 206 after save
MemStreamTest.exe Information: 0 : ToArray returned: 206 bytes
MemStreamTest.exe Information: 0 : Position: 13 after reconstruction

改变这个:

public Stream GenerateStreamFromString(string s)
  {
    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    writer.Write(Convert.FromBase64String(s));
    writer.Flush();
    stream.Position = 0;
    return stream;
  }

...至:

public Stream GenerateStreamFromString(string s)
{
    MemoryStream stream = new MemoryStream();
    var bytes = Convert.FromBase64String(s);
    stream.Write(bytes, 0, bytes.Length);
    Trace.TraceInformation($"Position: {stream.Position} after reconstruction");
    stream.Position = 0;
    return stream;
}


下面的Call示例在每个MemoryStream中产生 206 个字节。

var call = new Call {PhoneNumber = "0812345678", Duration = TimeSpan.FromMinutes(5)};

[Serializable]
public class Call
{
    public TimeSpan Duration { get; set; }
    public string PhoneNumber { get; set; }
}

结果:

MemStreamTest.exe Information: 0 : Position: 206 after save
MemStreamTest.exe Information: 0 : ToArray returned: 206 bytes
MemStreamTest.exe Information: 0 : Position: 206 after reconstruction

完整列表

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace MemStreamTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var program = new Program();
            program.Run();
        }

        private void Run()
        {
            var call = new Call {PhoneNumber = "0812345678", Duration = TimeSpan.FromMinutes(5)};
            var contents = SerializeObject(call);

            var other = deSerialize(contents);
        }

        public string SerializeObject<T>(T objectToSerialize)
        {
            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream memStr = new MemoryStream();
            try
            {
                bf.Serialize(memStr, objectToSerialize); // serialise as binary
                Trace.TraceInformation($"Position: {memStr.Position} after save");
                memStr.Position = 0;
                var bytes = memStr.ToArray();
                Trace.TraceInformation($"ToArray returned: {bytes.Length} bytes");
                
                return Convert.ToBase64String(bytes); // binary to Base64
            }
            finally
            {
                memStr.Close();
            }
        }

        public Call deSerialize(string Serialized)
        {
            Stream Fs = GenerateStreamFromString(Serialized);
            BinaryFormatter F = new BinaryFormatter();
            Call s1 = (Call)F.Deserialize(Fs);
            Fs.Close();
            return s1;
        }

        public Stream GenerateStreamFromString(string s)
        {
            MemoryStream stream = new MemoryStream();
            var bytes = Convert.FromBase64String(s);
            stream.Write(bytes, 0, bytes.Length);
            Trace.TraceInformation($"Position: {stream.Position} after reconstruction");
            stream.Position = 0;
            return stream;
        }
    }

    [Serializable]
    public class Call
    {
        public TimeSpan Duration { get; set; }
        public string PhoneNumber { get; set; }
    }
}

最后的想法

除非您真的想要 Base64 有效载荷,否则建议您使用 Newtonsoft Json。

您可以使用 Newtonsoft Jsonconvert 开箱即用地执行此操作:

var stringValue = JsonConvert.SerializeObject(entity);
var object = JsonConvert.DeserializeObject<T>(stringValue);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM