将对象列表写入文件

28

我可以将以下格式的销售员类提供给您:

class salesman
{
    public string name, address, email;
    public int sales;
}

我有另一个课程,用户输入姓名、地址、电子邮件和销售额。
然后将此输入添加到列表中。

List<salesman> salesmanList = new List<salesman>();
用户可以随意添加销售员到列表中,并可选择将该列表保存到他们选择的文件中(我可以将其限制为 .xml 或 .txt(哪个更合适))。 如何将此列表添加到文件中? 如果用户希望以后查看记录,则需要重新读取该文件到列表中。

3
你希望文件使用什么格式呢?你可以使用XML、.NET二进制序列化、Protocol Buffers、Thrift、JSON等很多选择。此外,我强烈建议你开始遵循.NET命名规范,并停止使用公共字段。 - Jon Skeet
1
我建议使用DataContracts:MSDN文档:http://msdn.microsoft.com/en-us/library/ms733127.aspx和http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx。 - Matthew Watson
1
是的,这取决于您希望如何存储它。您可以使用XML、Protobuf或JSON。有很多选择。 - Carlos Landeras
4个回答

50

像这样会起作用。它使用二进制格式(加载速度最快),但同样的代码也适用于使用不同序列化器的xml。

using System.IO;

    [Serializable]
    class salesman
    {
        public string name, address, email;
        public int sales;
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<salesman> salesmanList = new List<salesman>();
            string dir = @"c:\temp";
            string serializationFile = Path.Combine(dir, "salesmen.bin");

            //serialize
            using (Stream stream = File.Open(serializationFile, FileMode.Create))
            {
                var bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

                bformatter.Serialize(stream, salesmanList);
            }

            //deserialize
            using (Stream stream = File.Open(serializationFile, FileMode.Open))
            {
                var bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

                List<salesman>  salesman = (List<salesman>)bformatter.Deserialize(stream);
            }
        }
    }

在寻找一种替代将每个项目写成文本的方法... 很好的替代方案。 - user1853517
是的,在 [Serializable] 类之后,它对我非常有效。 - Sharif Lotfi
但是当我想在另一个应用程序中使用该文件时,旧的应用程序.dll就需要了,有没有一种方法可以在不依赖于应用程序dll的情况下进行序列化? - Sharif Lotfi

43
我刚刚写了一篇博客文章关于如何将对象的数据保存为二进制、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 XML 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 XML 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 XML.</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 list of salesman objects to file.
WriteToXmlFile<List<salesman>>("C:\salesmen.txt", salesmanList);

// Read the list of salesman objects from the file back into a variable.
List<salesman> salesmanList = ReadFromXmlFile<List<salesman>>("C:\salesmen.txt");

非常棒的答案,谢谢!正是我在寻找的(XML版本就是我需要的)。 :) - Jo Smo
非常棒的回答,30分钟内就给了我所需的一切。 - Alex Moreno
非常专业的回答,非常感谢你。 - Sina

2

如果您想使用JSON,那么使用Json.NET通常是最好的选择。

如果出于某种原因无法使用Json.NET,则可以使用.NET中提供的内置JSON支持。

您需要包含以下using语句,并添加对System.Web.Extentsions的引用。

using System.Web.Script.Serialization;

然后,您将使用这些工具对对象进行序列化和反序列化。
//Deserialize JSON to your Object
YourObject obj = new JavaScriptSerializer().Deserialize<YourObject>("File Contents");

//Serialize your object to JSON
string sJSON = new JavaScriptSerializer().Serialize(YourObject);

https://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer_methods(v=vs.110).aspx


0
如果您想进行 XML 序列化,可以使用内置的序列化器。为此,请将 [Serializable] 标志添加到类中:
[Serializable()]
class salesman
{
    public string name, address, email;
    public int sales;
}

然后,您可以重写“ToString()”方法,将数据转换为XML字符串:
public override string ToString()
    {
        string sData = "";
        using (MemoryStream oStream = new MemoryStream())
        {
            XmlSerializer oSerializer = new XmlSerializer(this.GetType());
            oSerializer.Serialize(oStream, this);
            oStream.Position = 0;
            sData = Encoding.UTF8.GetString(oStream.ToArray());
        }
        return sData;
    }

然后只需创建一个方法,将this.ToString()写入文件。

更新 上述提到的方法将单个条目序列化为xml。如果您需要序列化整个列表,则思路会有所不同。在这种情况下,您可以利用列表的可序列化性,前提是其内容也是可序列化的,并在某个外部类中使用序列化。

示例代码:

[Serializable()]
class salesman
{
    public string name, address, email;
    public int sales;
}

class salesmenCollection 
{
   List<salesman> salesmanList;

   public void SaveTo(string path){
       System.IO.File.WriteAllText (path, this.ToString());
   }    

   public override string ToString()
   {
     string sData = "";
     using (MemoryStream oStream = new MemoryStream())
      {
        XmlSerializer oSerializer = new XmlSerializer(this.GetType());
        oSerializer.Serialize(oStream, this);
        oStream.Position = 0;
        sData = Encoding.UTF8.GetString(oStream.ToArray());
      }
     return sData;
    }
}

1
a) 当使用 XmlSerializer 时,不需要 Serializable b) OP 尝试序列化一个 salesman 的列表,而不是单个实例 - I4V
关于b):SaveTo()函数将对salesmanList进行序列化... - Meister Schnitzel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接