【问题标题】:How to save/restore serializable object to/from file?如何在文件中保存/恢复可序列化对象?
【发布时间】:2019-02-10 11:08:37
【问题描述】:

我有一个对象列表,我需要将其保存在计算机的某个位置。我读过一些论坛,我知道对象必须是Serializable。但如果我能举个例子就好了。例如,如果我有以下内容:

[Serializable]
public class SomeClass
{
     public string someProperty { get; set; }
}

SomeClass object1 = new SomeClass { someProperty = "someString" };

但是我怎样才能将object1 存储在我的计算机中的某个位置,然后再检索呢?

【问题讨论】:

标签: c# serialization stream


【解决方案1】:

您可以使用 Newtonsoft 库中的 JsonConvert。 序列化对象并以 json 格式写入文件:

File.WriteAllText(filePath, JsonConvert.SerializeObject(obj));

并将其反序列化回对象:

var obj = JsonConvert.DeserializeObject<ObjType>(File.ReadAllText(filePath));

【讨论】:

    【解决方案2】:

    您可以使用以下内容:

        /// <summary>
        /// Serializes an object.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="serializableObject"></param>
        /// <param name="fileName"></param>
        public void SerializeObject<T>(T serializableObject, string fileName)
        {
            if (serializableObject == null) { return; }
    
            try
            {
                XmlDocument xmlDocument = new XmlDocument();
                XmlSerializer serializer = new XmlSerializer(serializableObject.GetType());
                using (MemoryStream stream = new MemoryStream())
                {
                    serializer.Serialize(stream, serializableObject);
                    stream.Position = 0;
                    xmlDocument.Load(stream);
                    xmlDocument.Save(fileName);
                }
            }
            catch (Exception ex)
            {
                //Log exception here
            }
        }
    
    
        /// <summary>
        /// Deserializes an xml file into an object list
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public T DeSerializeObject<T>(string fileName)
        {
            if (string.IsNullOrEmpty(fileName)) { return default(T); }
    
            T objectOut = default(T);
    
            try
            {
                XmlDocument xmlDocument = new XmlDocument();
                xmlDocument.Load(fileName);
                string xmlString = xmlDocument.OuterXml;
    
                using (StringReader read = new StringReader(xmlString))
                {
                    Type outType = typeof(T);
    
                    XmlSerializer serializer = new XmlSerializer(outType);
                    using (XmlReader reader = new XmlTextReader(read))
                    {
                        objectOut = (T)serializer.Deserialize(reader);
                    }
                }
            }
            catch (Exception ex)
            {
                //Log exception here
            }
    
            return objectOut;
        }
    

    【讨论】:

    • 不错!虽然DeSerializeObject 中的string attributeXml = string.Empty; 从未使用过;)
    • 无需在 using 块中调用阅读器的 close 方法。 Dispose() 是隐式的,即使在显式 Close() 之前的块内引发异常,也会发生。非常有用的代码块。
    • 如何使用这个函数保存对象列表我用过,但它只保存列表中的最后一个对象
    • 此方法不会保存内部或私有字段,您可以使用这个:github.com/mrbm2007/ObjectSaver
    【解决方案3】:

    **1。将 json 字符串转换为 base64string 并将其写入或附加到二进制文件中。 2. 从二进制文件中读取base64string并使用BsonReader反序列化。 **

     public static class BinaryJson
    {
        public static string SerializeToBase64String(this object obj)
        {
            JsonSerializer jsonSerializer = new JsonSerializer();
            MemoryStream objBsonMemoryStream = new MemoryStream();
            using (BsonWriter bsonWriterObject = new BsonWriter(objBsonMemoryStream))
            {
                jsonSerializer.Serialize(bsonWriterObject, obj);
                return Convert.ToBase64String(objBsonMemoryStream.ToArray());
            }           
            //return Encoding.ASCII.GetString(objBsonMemoryStream.ToArray());
        }
        public static T DeserializeToObject<T>(this string base64String)
        {
            byte[] data = Convert.FromBase64String(base64String);
            MemoryStream ms = new MemoryStream(data);
            using (BsonReader reader = new BsonReader(ms))
            {
                JsonSerializer serializer = new JsonSerializer();
                return serializer.Deserialize<T>(reader);
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      我刚刚写了a blog post on saving an object's data to Binary, XML, or Json。您是正确的,您必须使用 [Serializable] 属性装饰您的类,但前提是您使用的是二进制序列化。您可能更喜欢使用 XML 或 Json 序列化。以下是各种格式的功能。有关详细信息,请参阅我的博文。

      二进制

      /// <summary>
      /// Writes the given object instance to a binary file.
      /// <para>Object type (and all child types) must be decorated with the [Serializable] attribute.</para>
      /// <para>To prevent a variable from being serialized, decorate it with the [NonSerialized] attribute; cannot be applied to properties.</para>
      /// </summary>
      /// <typeparam name="T">The type of object being written to the binary file.</typeparam>
      /// <param name="filePath">The file path to write the object instance to.</param>
      /// <param name="objectToWrite">The object instance to write to the binary file.</param>
      /// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
      public static void WriteToBinaryFile<T>(string filePath, T objectToWrite, bool append = false)
      {
          using (Stream stream = File.Open(filePath, append ? FileMode.Append : FileMode.Create))
          {
              var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
              binaryFormatter.Serialize(stream, objectToWrite);
          }
      }
      
      /// <summary>
      /// Reads an object instance from a binary file.
      /// </summary>
      /// <typeparam name="T">The type of object to read from the binary file.</typeparam>
      /// <param name="filePath">The file path to read the object instance from.</param>
      /// <returns>Returns a new instance of the object read from the binary file.</returns>
      public static T ReadFromBinaryFile<T>(string filePath)
      {
          using (Stream stream = File.Open(filePath, FileMode.Open))
          {
              var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
              return (T)binaryFormatter.Deserialize(stream);
          }
      }
      

      XML

      需要将 System.Xml 程序集包含在您的项目中。

      /// <summary>
      /// Writes the given object instance to an XML file.
      /// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
      /// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [XmlIgnore] attribute.</para>
      /// <para>Object type must have a parameterless constructor.</para>
      /// </summary>
      /// <typeparam name="T">The type of object being written to the file.</typeparam>
      /// <param name="filePath">The file path to write the object instance to.</param>
      /// <param name="objectToWrite">The object instance to write to the file.</param>
      /// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
      public static void WriteToXmlFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
      {
          TextWriter writer = null;
          try
          {
              var serializer = new XmlSerializer(typeof(T));
              writer = new StreamWriter(filePath, append);
              serializer.Serialize(writer, objectToWrite);
          }
          finally
          {
              if (writer != null)
                  writer.Close();
          }
      }
      
      /// <summary>
      /// Reads an object instance from an XML file.
      /// <para>Object type must have a parameterless constructor.</para>
      /// </summary>
      /// <typeparam name="T">The type of object to read from the file.</typeparam>
      /// <param name="filePath">The file path to read the object instance from.</param>
      /// <returns>Returns a new instance of the object read from the XML file.</returns>
      public static T ReadFromXmlFile<T>(string filePath) where T : new()
      {
          TextReader reader = null;
          try
          {
              var serializer = new XmlSerializer(typeof(T));
              reader = new StreamReader(filePath);
              return (T)serializer.Deserialize(reader);
          }
          finally
          {
              if (reader != null)
                  reader.Close();
          }
      }
      

      Json

      您必须包含对 Newtonsoft.Json 程序集的引用,该程序集可从 Json.NET NuGet Package 获得。

      /// <summary>
      /// Writes the given object instance to a Json file.
      /// <para>Object type must have a parameterless constructor.</para>
      /// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
      /// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [JsonIgnore] attribute.</para>
      /// </summary>
      /// <typeparam name="T">The type of object being written to the file.</typeparam>
      /// <param name="filePath">The file path to write the object instance to.</param>
      /// <param name="objectToWrite">The object instance to write to the file.</param>
      /// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
      public static void WriteToJsonFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
      {
          TextWriter writer = null;
          try
          {
              var contentsToWriteToFile = JsonConvert.SerializeObject(objectToWrite);
              writer = new StreamWriter(filePath, append);
              writer.Write(contentsToWriteToFile);
          }
          finally
          {
              if (writer != null)
                  writer.Close();
          }
      }
      
      /// <summary>
      /// Reads an object instance from an Json file.
      /// <para>Object type must have a parameterless constructor.</para>
      /// </summary>
      /// <typeparam name="T">The type of object to read from the file.</typeparam>
      /// <param name="filePath">The file path to read the object instance from.</param>
      /// <returns>Returns a new instance of the object read from the Json file.</returns>
      public static T ReadFromJsonFile<T>(string filePath) where T : new()
      {
          TextReader reader = null;
          try
          {
              reader = new StreamReader(filePath);
              var fileContents = reader.ReadToEnd();
              return JsonConvert.DeserializeObject<T>(fileContents);
          }
          finally
          {
              if (reader != null)
                  reader.Close();
          }
      }
      

      示例

      // Write the contents of the variable someClass to a file.
      WriteToBinaryFile<SomeClass>("C:\someClass.txt", object1);
      
      // Read the file contents back into a variable.
      SomeClass object1= ReadFromBinaryFile<SomeClass>("C:\someClass.txt");
      

      【讨论】:

      • 我喜欢你的二进制序列化代码。但是在 WriteToBinaryFile 上,您为什么要附加到文件中?看来您想在所有情况下都创建一个新文件。否则会有一大堆关于反序列化的额外信息。
      • @publicwireless 是的,你可能是对的。当时我并没有多想。我只是想让 3 个函数的签名匹配:P
      • 使用append方法,在同一个文件中序列化多个对象,如何反序列化?如何在流中寻找?
      • 请在二进制序列化程序中添加注释,这将告知人们生成的数据带有程序集的强名称,并更改此版本的版本,而无需添加重定向绑定或在不添加重定向绑定的环境中运行尊重所述绑定(例如powershell)将失败
      • @JohnDemetriou 如果将多个内容保存到文件中,我建议将对象包装在某种形式的上下文对象中并序列化该对象(让对象管理器解析出您想要的部分)。如果您尝试保存的数据超出内存中的容量,您可能需要切换到对象存储(对象数据库)而不是文件。
      【解决方案5】:

      1。从文件中恢复对象

      Here,您可以通过两种方式从文件中反序列化对象。

      Solution-1:将文件读入字符串并将 JSON 反序列化为类型

      string json = File.ReadAllText(@"c:\myObj.json");
      MyObject myObj = JsonConvert.DeserializeObject<MyObject>(json);
      

      解决方案 2:直接从文件反序列化 JSON

      using (StreamReader file = File.OpenText(@"c:\myObj.json"))
      {
          JsonSerializer serializer = new JsonSerializer();
          MyObject myObj2 = (MyObject)serializer.Deserialize(file, typeof(MyObject));
      }
      

      2。将对象保存到文件

      来自here,您可以通过两种方式将对象序列化为文件。

      Solution-1:将 JSON 序列化为字符串,然后将字符串写入文件

      string json = JsonConvert.SerializeObject(myObj);
      File.WriteAllText(@"c:\myObj.json", json);
      

      解决方案 2:将 JSON 直接序列化为文件

      using (StreamWriter file = File.CreateText(@"c:\myObj.json"))
      {
          JsonSerializer serializer = new JsonSerializer();
          serializer.Serialize(file, myObj);
      }
      

      3。额外

      您可以通过以下命令从NuGet下载Newtonsoft.Json

      Install-Package Newtonsoft.Json
      

      【讨论】:

        【解决方案6】:

        您需要序列化为某些内容:即选择二进制或 xml(对于默认序列化程序)或编写自定义序列化代码以序列化为其他文本形式。

        一旦您选择了它,您的序列化将(通常)调用正在写入某种文件的 Stream。

        所以,如果我使用的是 XML 序列化,那么使用您的代码:

        var path = @"C:\Test\myserializationtest.xml";
        using(FileStream fs = new FileStream(path, FileMode.Create))
        {
            XmlSerializer xSer = new XmlSerializer(typeof(SomeClass));
        
            xSer.Serialize(fs, serializableObject);
        }
        

        然后,反序列化:

        using(FileStream fs = new FileStream(path, FileMode.Open)) //double check that...
        {
            XmlSerializer _xSer = new XmlSerializer(typeof(SomeClass));
        
            var myObject = _xSer.Deserialize(fs);
        }
        

        注意:此代码尚未编译,更不用说运行了 - 可能存在一些错误。此外,这假设完全开箱即用的序列化/反序列化。如果您需要自定义行为,则需要做额外的工作。

        【讨论】:

          猜你喜欢
          • 2011-09-01
          • 1970-01-01
          • 2010-11-01
          • 2016-05-12
          • 1970-01-01
          • 1970-01-01
          • 2013-11-13
          相关资源
          最近更新 更多