C# - 序列化/反序列化或保存/加载元组列表

时间:2013-12-29 09:17:25

标签: c# xml serialization tuples

我有一个列表,其中包含两个字符串的元组和25.000个元素

List<Tuple<string, string>> MyList

我试图找到一种方法来保存这个列表,然后加载它,因为每次从 MyList 开始构建真的需要时间。我试过了

using System;
using System.IO;
using System.Text;
using System.Xml.Serialization;

namespace CopyFiles
{
/// <summary>
/// Serializer class.  Load and Save classes from/to XML files.
/// </summary>

public class XSerial
{
    /// <summary>
    /// Load a class from a serialized XML file.
    /// </summary>
    /// <param name="filename">full path or path relative to the XML file</param>
    /// <param name="t">type of the class that is being retrieved (Use typeof(ClassName))</param>
    /// <returns>A populated version of the class, or null on failure</returns>
    /// <exception cref="Exception">Can throw several exceptions for IO and serialization loading</exception>
    public static T Load<T>(string filename)
    {
        T ob = default(T);
        using (Stream s = File.Open(filename, FileMode.Open))
        {
            StreamReader sr = new StreamReader(s);
            ob = DeserializeObject<T>(sr.ReadToEnd());
            s.Close();
        }
        return ob;
    }

    /// <summary>
    /// Save an instance of a class to an XML file
    /// </summary>
    /// <param name="filename">Full or relative path to the file</param>
    /// <param name="cls">Class to serialize and save.</param>
    /// <param name="t">Type of the class (use: typeof(ClassName)</param>
    /// <returns>True on success, False on failure</returns>
    public static void Save<T>(string filename, T cls)
    {
        using (Stream s = File.Open(filename, FileMode.Create))
        {
            using (StreamWriter sw = new StreamWriter(s))
            {
                sw.Write(SerializeObject<T>(cls));
                sw.Close();
                s.Close();
                return;
            }
        }
    }


    /// <summary>
    /// Serialize the object into an XML format
    /// </summary>
    /// <typeparam name="T">Type of object to serialize</typeparam>
    /// <param name="pObject">the object to serialize</param>
    /// <returns>a string representing the XML version of the object</returns>
    public static String SerializeObject<T>(T pObject)
    {
        MemoryStream memoryStream = new MemoryStream();
        UTF8Encoding encoding = new UTF8Encoding();

        XmlSerializer xs = new XmlSerializer(typeof(T));
        System.Xml.XmlTextWriter xmlTextWriter = new System.Xml.XmlTextWriter(memoryStream, Encoding.UTF8);
        xs.Serialize(xmlTextWriter, (object)pObject);
        memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
        return encoding.GetString(memoryStream.ToArray());
    }

    /// <summary>
    /// Deserialize the object back into the object from an XML string
    /// </summary>
    /// <typeparam name="T">Type of the object to restore</typeparam>
    /// <param name="pXmlizedString">The string that represents the object in XML</param>
    /// <returns>A new instance of the restored object</returns>
    public static T DeserializeObject<T>(String pXmlizedString)
    {
        UTF8Encoding encoding = new UTF8Encoding();
        XmlSerializer xs = new XmlSerializer(typeof(T));
        MemoryStream memoryStream = new MemoryStream(encoding.GetBytes(pXmlizedString));
        System.Xml.XmlTextWriter xmlTextWriter = new System.Xml.XmlTextWriter(memoryStream, Encoding.UTF8);
        return (T)xs.Deserialize(memoryStream);
    }
  }
}

适用于简单的List&lt; ...&gt;

class Program
{
    static void Main(string[] args)
    {
        List<string> MyList = null;
        try
        {
            MyList = XSerial.Load<List<string>>("MyList.xml");
        }
        catch (Exception e)
        {
            Console.WriteLine("Error: " + e.Message);
            // make sure the object won't cause errors.
            MyList = new List<string>();
        }

        Console.WriteLine("List Items:");
        foreach (string item in MyList)
        {
            Console.WriteLine("In list: " + item);
        }

        MyList.Add("Orange");
        MyList.Add("Blue");
        MyList.Add("Green");

        Console.WriteLine("Saving list...\n");
        try
        {
            XSerial.Save<List<string>>("MyList.xml", MyList);
        }
        catch (Exception e)
        {
            Console.WriteLine("Error Saving: " + e.Message);
            // nothing can be done about recovery.
        }

        Console.WriteLine("Press any key to continue...");
        Console.ReadKey();
    }
}

但不是带有元组的列表,因为XmlSerializer能够完成它的工作需要一个默认的构造函数。这是一个不带参数的构造函数。所有元组&lt; ...&gt;类有一个构造函数,构造函数需要一些参数。

我的问题:以上XSerial是否有办法为元组列表执行工作,还是应该使用其他类似http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx的内容?提前谢谢。

2 个答案:

答案 0 :(得分:2)

我最后使用以下(二元seriliazation)用于具有元组的案例列表

 List<Tuple<string, string>> MyList

我的代码

 List<Tuple<string, string>> MyList = new List<Tuple<string, string>>(); 

 if (File.Exists(@"filename.dat"))
        {
            //LOAD
            Console.WriteLine("Load filename.dat...");
            FileStream inStr = new FileStream(@"filename.dat", FileMode.Open);
            BinaryFormatter bf = new BinaryFormatter();
            MyList = bf.Deserialize(inStr) as List<Tuple<string, string>>;

        }
        else {
            //
            // Do here the list building/ Make the List<Tuple<string, string>> MyList
            //

            //SAVE
            FileStream stream = new FileStream(@"filename.dat", FileMode.Create);
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, MyList);
            stream.Close();            
        }

在我的情况下和我的笔记本电脑中,列表构建大约需要6分钟(~33,000元组元素),从我拥有“filename.dat”的时间开始只需1秒就可以加载它以便在我的程序中进一步使用。

答案 1 :(得分:0)

如果性能是一个问题,那么JSON格式和JSON.Net框架应该更好地满足您的需求。此外,至少同样重要的是,JSON.Net应该为您开箱即用。