Unity Dictionary序列化和反序列化及XML本地数据存储

发表于2018-07-05
评论0 2.2k浏览
Unity中可以通过接口ISerializationCallbackReceiver实现Dictionary序列化和反序列化。那对于如何处理XML本地数据存储呢?下面就给大家介绍下这两类。

首先是XML形式存储本地数据

XMLManager类
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
public class XMLManager{
    /// 数据对象转换xml字符串  
    public static string SerializeObject(object pObject, System.Type ty)  
    {  
        string XmlizedString = null;  
        MemoryStream memoryStream = new MemoryStream();  
        XmlSerializer xs = new XmlSerializer(ty);  
        XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);  
        xs.Serialize(xmlTextWriter, pObject);  
        memoryStream = (MemoryStream)xmlTextWriter.BaseStream;  
        XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());  
        return XmlizedString;  
    }
    /// xml字符串转换数据对象  
    public static object DeserializeObject(string pXmlizedString, System.Type ty)  
    {  
        XmlSerializer xs = new XmlSerializer(ty);  
        MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(pXmlizedString));  
        XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);  
        return xs.Deserialize(memoryStream);  
    }
    /// <summary>
    /// UTF8字节数组转字符串  
    /// </summary>
    /// <param name="characters"></param>
    /// <returns></returns>
    public static string UTF8ByteArrayToString(byte[] characters)  
    {  
        UTF8Encoding encoding = new UTF8Encoding();  
        string constructedString = encoding.GetString(characters);  
        return (constructedString);  
    }
    /// <summary>
    /// 字符串转UTF8字节数组
    /// </summary>
    /// <param name="pXmlString"></param>
    /// <returns></returns>
    public static byte[] StringToUTF8ByteArray(System.String pXmlString)  
    {  
        UTF8Encoding encoding = new UTF8Encoding();  
        byte[] byteArray = encoding.GetBytes(pXmlString);  
        return byteArray;  
    }
    /// 创建文本文件  
    public static void CreateTextFile(string fileName, string strFileData, bool isEncryption)
    {
        StreamWriter writer;                               //写文件流  
        string strWriteFileData;
        if (isEncryption)
        {
            strWriteFileData = Encrypt(strFileData);  //是否加密处理  
        }
        else
        {
            strWriteFileData = strFileData;             //写入的文件数据  
        }
        writer = File.CreateText(fileName);
        writer.Write(strWriteFileData);
        writer.Close();                                    //关闭文件流  
    }
    /// 读取文本文件  
    public static string LoadTextFile(string fileName, bool isEncryption)
    {
        StreamReader sReader;                              //读文件流  
        string dataString;                                 //读出的数据字符串  
        sReader = File.OpenText(fileName);
        dataString = sReader.ReadToEnd();
        sReader.Close();                                   //关闭读文件流  
        if (isEncryption)
        {
            return Decrypt(dataString);                      //是否解密处理  
        }
        else
        {
            return dataString;
        }
    }
    /// 加密方法  
    /// 描述: 加密和解密采用相同的key,具体值自己填,但是必须为32位  
    public static string Encrypt(string toE)
    {
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes("12348578902223367877723456789012");
        RijndaelManaged rDel = new RijndaelManaged();
        rDel.Key = keyArray;
        rDel.Mode = CipherMode.ECB;
        rDel.Padding = PaddingMode.PKCS7;
        ICryptoTransform cTransform = rDel.CreateEncryptor();
        byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toE);
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
        return Convert.ToBase64String(resultArray, 0, resultArray.Length);
    }
    /// 解密方法  
    /// 描述: 加密和解密采用相同的key,具体值自己填,但是必须为32位  
    public static string Decrypt(string toD)
    {
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes("12348578902223367877723456789012");
        RijndaelManaged rDel = new RijndaelManaged();
        rDel.Key = keyArray;
        rDel.Mode = CipherMode.ECB;
        rDel.Padding = PaddingMode.PKCS7;
        ICryptoTransform cTransform = rDel.CreateDecryptor();
        byte[] toEncryptArray = Convert.FromBase64String(toD);
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
        return UTF8Encoding.UTF8.GetString(resultArray);
    }
    /// <summary>
    /// 写入数据
    /// </summary>
    /// <param name="pObject"></param>
    /// <param name="ty"></param>
    /// <param name="dataPath"></param>
    public static void XmlLocalStorageWrite(object pObject, System.Type ty, string dataPath)
    {
        //存储数据  
        string s = SerializeObject(pObject, ty);
        //创建XML文件且写入数据  
        CreateTextFile(dataPath, s, false);
    }
}

相比PlayerPrefs,能存储自定义数据结构的数据,
public class User
{
    private string name;
    private string pas;
}
//user[],Link<user>等都可以存储在本地,但Dictionary<int,user>不行

xml存储和反序列化获取方法
 public static string dataPathSave = "F:/unityLearning/Assets/Save/";//路径
  public static List<user> userList = new List<user>();
 XMLManager.XmlLocalStorageWrite(userList, typeof(List<user>), dataPathSave + "user");//存储
//反序列化获取
 string strTemp = XMLManager.LoadTextFile(dataPathSave + "user", false);
 List<user> List = XMLManager.DeserializeObject(strTemp, typeof(List<user>)) as List<user>;

Dictionary序列化和反序列化

之前提到dictionary不能成功,所有有了下面的方法
DictionaryXML
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Xml.Serialization;
public class DictionaryXML
{
    [Serializable]
    public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
    {
        #region 构造函数  
        public SerializableDictionary()
            : base()
        {
        }
        public SerializableDictionary(IDictionary<TKey, TValue> dictionary)
            : base(dictionary)
        {
        }
        public SerializableDictionary(IEqualityComparer<TKey> comparer)
            : base(comparer)
        {
        }
        public SerializableDictionary(int capacity)
            : base(capacity)
        {
        }
        public SerializableDictionary(int capacity, IEqualityComparer<TKey> comparer)
            : base(capacity, comparer)
        {
        }
        protected SerializableDictionary(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
        #endregion 构造函数  
        #region IXmlSerializable Members  
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }
        /// <summary>  
        /// 从对象的 XML 表示形式生成该对象  
        /// </summary>  
        /// <param name="reader"></param>  
        public void ReadXml(System.Xml.XmlReader reader)
        {
            XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
            XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
            bool wasEmpty = reader.IsEmptyElement;
            reader.Read();
            if (wasEmpty)
                return;
            while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
            {
                reader.ReadStartElement("item");
                reader.ReadStartElement("key");
                TKey key = (TKey)keySerializer.Deserialize(reader);
                reader.ReadEndElement();
                reader.ReadStartElement("value");
                TValue value = (TValue)valueSerializer.Deserialize(reader);
                reader.ReadEndElement();
                this.Add(key, value);
                reader.ReadEndElement();
                reader.MoveToContent();
            }
            reader.ReadEndElement();
        }
        /**/
        /// <summary>  
        /// 将对象转换为其 XML 表示形式  
        /// </summary>  
        /// <param name="writer"></param>  
        public void WriteXml(System.Xml.XmlWriter writer)
        {
            XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
            XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
            foreach (TKey key in this.Keys)
            {
                writer.WriteStartElement("item");
                writer.WriteStartElement("key");
                keySerializer.Serialize(writer, key);
                writer.WriteEndElement();
                writer.WriteStartElement("value");
                TValue value = this[key];
                valueSerializer.Serialize(writer, value);
                writer.WriteEndElement();
                writer.WriteEndElement();
            }
        }
        #endregion IXmlSerializable Members  
    }
}

调用
 public static DictionaryXML.SerializableDictionary<string, user> Dic = new DictionaryXML.SerializableDictionary<string, user>();//不能是 public static Dictionary<string, user> Dic = new Dictionary<string, user>();
//存储
 using (FileStream fileStream = new FileStream(dataPathSave + "pokraceDic", FileMode.Create))
        {
            XmlSerializer xmlFormatter = new XmlSerializer(typeof(DictionaryXML.SerializableDictionary<string, user>));
            xmlFormatter.Serialize(fileStream,Dic);
        }
//反序列化获取存储的dictionary
using (FileStream fileStream = new FileStream(dataPathSave + "user", FileMode.Open))
                {
                    XmlSerializer xmlFormatter = new XmlSerializer(typeof(DictionaryXML.SerializableDictionary<string, user>));
                    Dic = (DictionaryXML.SerializableDictionary<string, user>)xmlFormatter.Deserialize(fileStream);
                }

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引