1. 程式人生 > >XML檔案的序列化和反序列化

XML檔案的序列化和反序列化


一、編寫資料實體類,如下所示:

/***
 *
 *  Title: 
 *         資料持久化技術
 *
 *  Description:
 *        功能:
 *            XML讀寫
 *            關卡資料物件
 *
 *  Date: 2018
 * 
 *  Version: 1.0
 *
 *  Modify Recorder:
 *     
 */
using UnityEngine;
using System.Collections;

public class LevelData{
    public int LevelNumber;					            //關卡編號
    public bool IsUnlock;						    //關卡是否解鎖
    public string LevelName;						    //關卡名稱
    public LevelDetailInfo LevelDetailInfos;			            //關卡詳情要求


    public LevelData(){}

    public LevelData(int levelNumber, bool isUnlock, string  levelname,LevelDetailInfo detailInfo){
        this.LevelNumber = levelNumber;
        this.IsUnlock = isUnlock;
        this.LevelName = levelname;
        this.LevelDetailInfos = detailInfo;        
    }
}
/***
 *
 *  Title: 
 *         資料持久化技術
 *
 *  Description:
 *        功能:
 *            XML讀寫
 *            資料物件內嵌物件: 關卡詳細資訊
 *
 *  Date: 2017
 * 
 *  Version: 1.0
 *
 *  Modify Recorder:
 *     
 */
using UnityEngine;
using System.Collections;

public class LevelDetailInfo{
    public string DemandOfPass;						       //通關要求
    public string DetailContent;                                               //詳細內容


    public LevelDetailInfo() { }
    public LevelDetailInfo(string demandOfPass, string content){
        this.DemandOfPass = demandOfPass;
        this.DetailContent = content;
    }
}

二、編寫XML的核心讀/寫操作類(包含序列化、反序列化、加密)

/***
 *
 *  Title: 
 *         資料持久化技術
 *
 *  Description:
 *        功能:
 *            XML讀寫
 *            XML 讀寫核心類
 *
 *  Date: 2017
 * 
 *  Version: 1.0
 *
 *  Modify Recorder:
 *     
 */
using System.Collections;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System;

public class XmlOperation{
    private static XmlOperation _Instance = null;          //靜態類物件

    public static XmlOperation GetInstance()
    {
        if (_Instance == null)
        {
            _Instance = new XmlOperation();
        }
        return _Instance;
    }


    /// <summary>  加密方法
    /// 加密方法
    /// 
    /// 描述: 加密和解密採用相同的key,具體值自己填,但是必須為32位
    /// </summary>
    /// <param name="toE"></param>
    /// <returns></returns>
	public 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);
	}

    /// <summary>  解密方法
    /// 解密方法
    /// 
    /// 描述: 加密和解密採用相同的key,具體值自己填,但是必須為32位
    /// </summary>
    /// <param name="toD"></param>
    /// <returns></returns>
	public 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>
    /// <returns></returns>
	public 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;
	}

    /// <summary> 反序列化物件
    /// 反序列化物件
    /// </summary>
    /// <param name="pXmlizedString"></param>
    /// <param name="ty"></param>
    /// <returns></returns>
	public 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> 建立XML檔案
    /// 建立XML檔案
    /// </summary>
    /// <param name="fileName">檔名稱</param>
    /// <param name="strFileData">寫入的檔案資料</param>
	public void CreateXML(string fileName,string strFileData){
        StreamWriter writer;                               //寫檔案流

        //string strWriteFileData = Encrypt(strFileData);  //是否加密處理
        string strWriteFileData = strFileData;             //寫入的檔案資料
		writer = File.CreateText(fileName);
        writer.Write(strWriteFileData);
		writer.Close();                                    //關閉檔案流
	}

    /// <summary> 讀取XML檔案
    /// 讀取XML檔案
    /// </summary>
    /// <param name="fileName">檔名稱</param>
    /// <returns></returns>
	public string LoadXML(string fileName){
        StreamReader sReader;                              //讀檔案流
        string dataString;                                 //讀出的資料字串

		sReader = File.OpenText(fileName);
		dataString = sReader.ReadToEnd();
		sReader.Close();                                   //關閉讀檔案流
		//return Decrypt(dataString);                      //是否解密處理
        return dataString;
	}
	
	//判斷是否存在檔案
	public bool hasFile(String fileName){
		return File.Exists(fileName);
	}

    //UTF8位元組陣列轉字串
	public string UTF8ByteArrayToString(byte[] characters  ){    
		UTF8Encoding encoding  = new UTF8Encoding();
		string constructedString  = encoding.GetString(characters);
		return (constructedString);
	}

    //字串轉UTF8位元組陣列
	public byte[] StringToUTF8ByteArray(String pXmlString ){
		UTF8Encoding encoding  = new UTF8Encoding();
		byte[] byteArray  = encoding.GetBytes(pXmlString);
		return byteArray;
	}
}


三、XML測試類

/***
 *
 *  Title: 
 *          資料持久化技術
 *
 *  Description:
 *        功能:
 *            XML讀寫
 *            XML讀寫測試主指令碼
 *
 *  Date: 2017
 * 
 *  Version: 1.0
 *
 *  Modify Recorder:
 *     
 */

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class TestXML : MonoBehaviour {
    //關卡資料集合
    public List<LevelData> listLevelData = new List<LevelData>(); //關卡資料集合
    //資料持久化路徑
    static string _fileName;

	void Start () {
        _fileName = Application.persistentDataPath + "/UnityProjectLevelData";
        
        //建立測試用例
        TestCase();
        //儲存物件到XML
        StoreDateToXMLFile();
        //讀取測試
        ReadDateFromXMLFile();
	}

 
    /// <summary>
    /// 定義初始化測試用例資料
    /// </summary>
    public void TestCase(){
        LevelDetailInfo levelDetailInfo0=new 
            LevelDetailInfo("消除2課紅鑽石", "需要同時消除2課以上的紅色鑽石,時間5分鐘內完成");
        LevelDetailInfo levelDetailInfo1 = new 
            LevelDetailInfo("消除5課紅鑽石", "需要同時消除5課以上的紅色鑽石,時間2分鐘內完成");
        listLevelData.Add(new LevelData(0, true, "第一關", levelDetailInfo0));
        listLevelData.Add(new LevelData(1, true, "第二關", levelDetailInfo1));
    }

    /// <summary>
    /// 儲存資料到XML檔案
    /// </summary>
    public void StoreDateToXMLFile()
    {
        //物件序列化
        string s = XmlOperation.GetInstance().SerializeObject(listLevelData, typeof(List<LevelData>));
        print("持久化xml 資料 s=" + s);
        print("建立XML檔案_fileName=" + _fileName);
        //建立XML檔案且寫入資料
        XmlOperation.GetInstance().CreateXML(_fileName, s);
        print("建立XML完成");
    }

    /// <summary>
    /// 從XML檔案中讀取資料
    /// </summary>
    public void ReadDateFromXMLFile(){
        try{
            //讀取資料
            string strTemp = XmlOperation.GetInstance().LoadXML(_fileName);
            print("讀取的原始XML資料字串: " + strTemp);
            //反序列化物件
            listLevelData = XmlOperation.GetInstance().DeserializeObject
                (strTemp, typeof(List<LevelData>)) as List<LevelData>;

            //讀取出來
            foreach (LevelData dataItem in listLevelData){
                print("");
                print("關卡序號: " + dataItem.LevelNumber);
                print("關卡名稱: " + dataItem.LevelName);
                print("關卡鎖定: " + dataItem.IsUnlock);
                print("過關要求: " + dataItem.LevelDetailInfos.DemandOfPass);
                print("詳細說明: " + dataItem.LevelDetailInfos.DetailContent);
            }
        }
        catch{
            print("系統讀取XML出現錯誤,請檢查");
        }
    }
}


 注:本示例來自《Unity3D/2D遊戲開發從0到1》第26章資料持久化內容。