C# Note4:XML序列化和反序列化(含加密解密等)

前言

       在项目中,我们经常用到各种配置文件,比如xml文件、binary文件等等,这里主要根据实践经验介绍下xml文件的序列化和反序列化(毕竟最常用)。

实践背景:我要做一个用户管理功能,用户账号信息存储在xml/binary文件中,需要对其进行读写,而且为了不让用户修改,必须对其加密,当时想的有3种做法:

(1)实现读写xml配置文件,并将关键信息加密;

(2)实现读写binary配置文件,并将关键信息加密;

(3)直接对配置文件进行加密解密和读写,不管它所使用的文件格式是xml、binary或其它。

这三种做法我都实现了,不过经过最后manager的确认觉得采用第(3)种方法最好。

 

方法一:

(推荐:Load and save objects to XML using serialization  本方法参考其思路)

(1)在我们将对象序列化为XML之前,对象的类代码必须包含各种自定义元数据属性(例如,[XmlAttributeAttribute(DataType = " date "])告诉编译器类及其字段和/或属性可以被序列化。

using System;
using System.Xml.Serialization;
using System.Collections.ObjectModel;

namespace XXX.GlobalTypes
{
    /// <summary>
    /// Save user account information
    /// </summary>
    [Serializable]
    [XmlRoot("UserManagement")]
    public class UserAccountInfo
    {
        private readonly Collection<UserInfo> _users = new Collection<UserInfo>();

        [XmlElement("UserAccountInfo")]
        public Collection<UserInfo> Users
        {
            get { return this._users; }
        }
    }

    [Serializable]
    public class UserInfo
    {

        [XmlElement("UserName")]
        public string UserName
        {
            get;
            set;
        }

        [XmlElement("UserPwd")]
        public string UserPwd
        {
            get;
            set;
        }

        [XmlElement("UserRole")]
        public ACCESS_LEVEL UserRole
        {
            get;
            set;
        }

        [XmlElement("Description")]
        public string Description
        {
            get;
            set;
        }
    }

}

(2)封装XML序列化的类(其中作为样例,我加入了加密解密的参数tDESkey,在将数据对象保存到xml文件后进行加密,从xml文件中读取数据前先进行解密):

  1 using System;
  2 using System.Xml;
  3 using System.Security.Cryptography;
  4 using System.Security.Cryptography.Xml;
  5 using System.Xml.Serialization;     // For serialization of an object to an XML Document file.
  6 using System.Runtime.Serialization.Formatters.Binary; // For serialization of an object to an XML Binary file.
  7 using System.IO;                 // For reading/writing data to an XML file.
  8 using System.IO.IsolatedStorage; // For accessing user isolated data.
  9 
 10 namespace XXX.Utilities.Common
 11 {
 12     /// <summary>
 13     /// Serialization format types.
 14     /// </summary>
 15     public enum SerializedFormat
 16     {
 17         /// <summary>
 18         /// Binary serialization format.
 19         /// </summary>
 20         Binary,
 21 
 22         /// <summary>
 23         /// Document serialization format.
 24         /// </summary>
 25         Document
 26     }
 27 
 28 
 29     /// <summary>
 30     /// Facade to XML serialization and deserialization of strongly typed objects to/from an XML file.
 31     /// 
 32     /// References: XML Serialization at http://samples.gotdotnet.com/:
 33     /// http://samples.gotdotnet.com/QuickStart/howto/default.aspx?url=/quickstart/howto/doc/xmlserialization/rwobjfromxml.aspx
 34     /// </summary>
 35     public static class ObjectXMLSerializer<T> where T : class // Specify that T must be a class.
 36     {
 37         #region Load methods
 38 
 39         /// <summary>
 40         /// Loads an object from an XML file in Document format.
 41         /// </summary>
 42         /// <example>
 43         /// <code>
 44         /// serializableObject = ObjectXMLSerializer&lt;SerializableObject&gt;.Load(@"C:\XMLObjects.xml");
 45         /// </code>
 46         /// </example>
 47         /// <param name="path">Path of the file to load the object from.</param>
 48         /// <returns>Object loaded from an XML file in Document format.</returns>
 49         public static T Load(string path, TripleDESCryptoServiceProvider tDESkey)
 50         {
 51             T serializableObject = LoadFromDocumentFormat(null, path, null, tDESkey);
 52             return serializableObject;
 53         }
 54 
 55         /// <summary>
 56         /// Loads an object from an XML file using a specified serialized format.
 57         /// </summary>
 58         /// <example>
 59         /// <code>
 60         /// serializableObject = ObjectXMLSerializer&lt;SerializableObject&gt;.Load(@"C:\XMLObjects.xml", SerializedFormat.Binary);
 61         /// </code>
 62         /// </example>        
 63         /// <param name="path">Path of the file to load the object from.</param>
 64         /// <param name="serializedFormat">XML serialized format used to load the object.</param>
 65         /// <returns>Object loaded from an XML file using the specified serialized format.</returns>
 66         public static T Load(string path, SerializedFormat serializedFormat, TripleDESCryptoServiceProvider tDESkey)
 67         {
 68             T serializableObject = null;
 69 
 70             switch (serializedFormat)
 71             {
 72                 case SerializedFormat.Binary:
 73                     serializableObject = LoadFromBinaryFormat(path, null);
 74                     break;
 75 
 76                 case SerializedFormat.Document:
 77                 default:
 78                     serializableObject = LoadFromDocumentFormat(null, path, null, tDESkey);
 79                     break;
 80             }
 81 
 82             return serializableObject;
 83         }
 84 
 85         /// <summary>
 86         /// Loads an object from an XML file in Document format, supplying extra data types to enable deserialization of custom types within the object.
 87         /// </summary>
 88         /// <example>
 89         /// <code>
 90         /// serializableObject = ObjectXMLSerializer&lt;SerializableObject&gt;.Load(@"C:\XMLObjects.xml", new Type[] { typeof(MyCustomType) });
 91         /// </code>
 92         /// </example>
 93         /// <param name="path">Path of the file to load the object from.</param>
 94         /// <param name="extraTypes">Extra data types to enable deserialization of custom types within the object.</param>
 95         /// <returns>Object loaded from an XML file in Document format.</returns>
 96         public static T Load(string path, System.Type[] extraTypes, TripleDESCryptoServiceProvider tDESkey)
 97         {
 98             T serializableObject = LoadFromDocumentFormat(extraTypes, path, null, tDESkey);
 99             return serializableObject;
100         }
101 
102         /// <summary>
103         /// Loads an object from an XML file in Document format, located in a specified isolated storage area.
104         /// </summary>
105         /// <example>
106         /// <code>
107         /// serializableObject = ObjectXMLSerializer&lt;SerializableObject&gt;.Load("XMLObjects.xml", IsolatedStorageFile.GetUserStoreForAssembly());
108         /// </code>
109         /// </example>
110         /// <param name="fileName">Name of the file in the isolated storage area to load the object from.</param>
111         /// <param name="isolatedStorageDirectory">Isolated storage area directory containing the XML file to load the object from.</param>
112         /// <returns>Object loaded from an XML file in Document format located in a specified isolated storage area.</returns>
113         public static T Load(string fileName, IsolatedStorageFile isolatedStorageDirectory, TripleDESCryptoServiceProvider tDESkey)
114         {
115             T serializableObject = LoadFromDocumentFormat(null, fileName, isolatedStorageDirectory, tDESkey);
116             return serializableObject;
117         }
118 
119         /// <summary>
120         /// Loads an object from an XML file located in a specified isolated storage area, using a specified serialized format.
121         /// </summary>
122         /// <example>
123         /// <code>
124         /// serializableObject = ObjectXMLSerializer&lt;SerializableObject&gt;.Load("XMLObjects.xml", IsolatedStorageFile.GetUserStoreForAssembly(), SerializedFormat.Binary);
125         /// </code>
126         /// </example>        
127         /// <param name="fileName">Name of the file in the isolated storage area to load the object from.</param>
128         /// <param name="isolatedStorageDirectory">Isolated storage area directory containing the XML file to load the object from.</param>
129         /// <param name="serializedFormat">XML serialized format used to load the object.</param>        
130         /// <returns>Object loaded from an XML file located in a specified isolated storage area, using a specified serialized format.</returns>
131         public static T Load(string fileName, IsolatedStorageFile isolatedStorageDirectory, SerializedFormat serializedFormat, TripleDESCryptoServiceProvider tDESkey)
132         {
133             T serializableObject = null;
134 
135             switch (serializedFormat)
136             {
137                 case SerializedFormat.Binary:
138                     serializableObject = LoadFromBinaryFormat(fileName, isolatedStorageDirectory);
139                     break;
140 
141                 case SerializedFormat.Document:
142                 default:
143                     serializableObject = LoadFromDocumentFormat(null, fileName, isolatedStorageDirectory, tDESkey);
144                     break;
145             }
146 
147             return serializableObject;
148         }
149 
150         /// <summary>
151         /// Loads an object from an XML file in Document format, located in a specified isolated storage area, and supplying extra data types to enable deserialization of custom types within the object.
152         /// </summary>
153         /// <example>
154         /// <code>
155         /// serializableObject = ObjectXMLSerializer&lt;SerializableObject&gt;.Load("XMLObjects.xml", IsolatedStorageFile.GetUserStoreForAssembly(), new Type[] { typeof(MyCustomType) });
156         /// </code>
157         /// </example>        
158         /// <param name="fileName">Name of the file in the isolated storage area to load the object from.</param>
159         /// <param name="isolatedStorageDirectory">Isolated storage area directory containing the XML file to load the object from.</param>
160         /// <param name="extraTypes">Extra data types to enable deserialization of custom types within the object.</param>
161         /// <returns>Object loaded from an XML file located in a specified isolated storage area, using a specified serialized format.</returns>
162         public static T Load(string fileName, IsolatedStorageFile isolatedStorageDirectory, System.Type[] extraTypes, TripleDESCryptoServiceProvider tDESkey)
163         {
164             T serializableObject = LoadFromDocumentFormat(null, fileName, isolatedStorageDirectory, tDESkey);
165             return serializableObject;
166         }
167 
168         #endregion
169 
170         #region Save methods
171 
172         /// <summary>
173         /// Saves an object to an XML file in Document format.
174         /// </summary>
175         /// <example>
176         /// <code>        
177         /// SerializableObject serializableObject = new SerializableObject();
178         /// 
179         /// ObjectXMLSerializer&lt;SerializableObject&gt;.Save(serializableObject, @"C:\XMLObjects.xml");
180         /// </code>
181         /// </example>
182         /// <param name="serializableObject">Serializable object to be saved to file.</param>
183         /// <param name="path">Path of the file to save the object to.</param>
184         public static void Save(T serializableObject, string path, TripleDESCryptoServiceProvider tDESkey)
185         {
186             SaveToDocumentFormat(serializableObject, null, path, null, tDESkey);
187         }
188 
189         /// <summary>
190         /// Saves an object to an XML file using a specified serialized format.
191         /// </summary>
192         /// <example>
193         /// <code>
194         /// SerializableObject serializableObject = new SerializableObject();
195         /// 
196         /// ObjectXMLSerializer&lt;SerializableObject&gt;.Save(serializableObject, @"C:\XMLObjects.xml", SerializedFormat.Binary);
197         /// </code>
198         /// </example>
199         /// <param name="serializableObject">Serializable object to be saved to file.</param>
200         /// <param name="path">Path of the file to save the object to.</param>
201         /// <param name="serializedFormat">XML serialized format used to save the object.</param>
202         public static void Save(T serializableObject, string path, SerializedFormat serializedFormat, TripleDESCryptoServiceProvider tDESkey)
203         {
204             switch (serializedFormat)
205             {
206                 case SerializedFormat.Binary:
207                     SaveToBinaryFormat(serializableObject, path, null);
208                     break;
209 
210                 case SerializedFormat.Document:
211                 default:
212                     SaveToDocumentFormat(serializableObject, null, path, null, tDESkey);
213                     break;
214             }
215         }
216 
217         /// <summary>
218         /// Saves an object to an XML file in Document format, supplying extra data types to enable serialization of custom types within the object.
219         /// </summary>
220         /// <example>
221         /// <code>        
222         /// SerializableObject serializableObject = new SerializableObject();
223         /// 
224         /// ObjectXMLSerializer&lt;SerializableObject&gt;.Save(serializableObject, @"C:\XMLObjects.xml", new Type[] { typeof(MyCustomType) });
225         /// </code>
226         /// </example>
227         /// <param name="serializableObject">Serializable object to be saved to file.</param>
228         /// <param name="path">Path of the file to save the object to.</param>
229         /// <param name="extraTypes">Extra data types to enable serialization of custom types within the object.</param>
230         public static void Save(T serializableObject, string path, System.Type[] extraTypes, TripleDESCryptoServiceProvider tDESkey)
231         {
232             SaveToDocumentFormat(serializableObject, extraTypes, path, null, tDESkey);
233         }
234 
235         /// <summary>
236         /// Saves an object to an XML file in Document format, located in a specified isolated storage area.
237         /// </summary>
238         /// <example>
239         /// <code>        
240         /// SerializableObject serializableObject = new SerializableObject();
241         /// 
242         /// ObjectXMLSerializer&lt;SerializableObject&gt;.Save(serializableObject, "XMLObjects.xml", IsolatedStorageFile.GetUserStoreForAssembly());
243         /// </code>
244         /// </example>
245         /// <param name="serializableObject">Serializable object to be saved to file.</param>
246         /// <param name="fileName">Name of the file in the isolated storage area to save the object to.</param>
247         /// <param name="isolatedStorageDirectory">Isolated storage area directory containing the XML file to save the object to.</param>
248         public static void Save(T serializableObject, string fileName, IsolatedStorageFile isolatedStorageDirectory, TripleDESCryptoServiceProvider tDESkey)
249         {
250             SaveToDocumentFormat(serializableObject, null, fileName, isolatedStorageDirectory, tDESkey);
251         }
252 
253         /// <summary>
254         /// Saves an object to an XML file located in a specified isolated storage area, using a specified serialized format.
255         /// </summary>
256         /// <example>
257         /// <code>        
258         /// SerializableObject serializableObject = new SerializableObject();
259         /// 
260         /// ObjectXMLSerializer&lt;SerializableObject&gt;.Save(serializableObject, "XMLObjects.xml", IsolatedStorageFile.GetUserStoreForAssembly(), SerializedFormat.Binary);
261         /// </code>
262         /// </example>
263         /// <param name="serializableObject">Serializable object to be saved to file.</param>
264         /// <param name="fileName">Name of the file in the isolated storage area to save the object to.</param>
265         /// <param name="isolatedStorageDirectory">Isolated storage area directory containing the XML file to save the object to.</param>
266         /// <param name="serializedFormat">XML serialized format used to save the object.</param>        
267         public static void Save(T serializableObject, string fileName, IsolatedStorageFile isolatedStorageDirectory, SerializedFormat serializedFormat, TripleDESCryptoServiceProvider tDESkey)
268         {
269             switch (serializedFormat)
270             {
271                 case SerializedFormat.Binary:
272                     SaveToBinaryFormat(serializableObject, fileName, isolatedStorageDirectory);
273                     break;
274 
275                 case SerializedFormat.Document:
276                 default:
277                     SaveToDocumentFormat(serializableObject, null, fileName, isolatedStorageDirectory, tDESkey);
278                     break;
279             }
280         }
281 
282         /// <summary>
283         /// Saves an object to an XML file in Document format, located in a specified isolated storage area, and supplying extra data types to enable serialization of custom types within the object.
284         /// </summary>
285         /// <example>
286         /// <code>
287         /// SerializableObject serializableObject = new SerializableObject();
288         /// 
289         /// ObjectXMLSerializer&lt;SerializableObject&gt;.Save(serializableObject, "XMLObjects.xml", IsolatedStorageFile.GetUserStoreForAssembly(), new Type[] { typeof(MyCustomType) });
290         /// </code>
291         /// </example>        
292         /// <param name="serializableObject">Serializable object to be saved to file.</param>
293         /// <param name="fileName">Name of the file in the isolated storage area to save the object to.</param>
294         /// <param name="isolatedStorageDirectory">Isolated storage area directory containing the XML file to save the object to.</param>
295         /// <param name="extraTypes">Extra data types to enable serialization of custom types within the object.</param>
296         public static void Save(T serializableObject, string fileName, IsolatedStorageFile isolatedStorageDirectory, System.Type[] extraTypes, TripleDESCryptoServiceProvider tDESkey)
297         {
298             SaveToDocumentFormat(serializableObject, null, fileName, isolatedStorageDirectory, tDESkey);
299         }
300 
301         #endregion
302 
303         #region Private
304 
305         private static FileStream CreateFileStream(IsolatedStorageFile isolatedStorageFolder, string path)
306         {
307             FileStream fileStream = null;
308 
309             if (isolatedStorageFolder == null)
310                 fileStream = new FileStream(path, FileMode.OpenOrCreate);
311             else
312                 fileStream = new IsolatedStorageFileStream(path, FileMode.OpenOrCreate, isolatedStorageFolder);
313 
314             return fileStream;
315         }
316 
317         private static T LoadFromBinaryFormat(string path, IsolatedStorageFile isolatedStorageFolder)
318         {
319             T serializableObject = null;
320 
321             using (FileStream fileStream = CreateFileStream(isolatedStorageFolder, path))
322             {
323                 BinaryFormatter binaryFormatter = new BinaryFormatter();
324                 serializableObject = binaryFormatter.Deserialize(fileStream) as T;
325             }
326 
327             return serializableObject;
328         }
329 
330         private static T LoadFromDocumentFormat(System.Type[] extraTypes, string path, IsolatedStorageFile isolatedStorageFolder, TripleDESCryptoServiceProvider tDESkey)
331         {
332             XmlDocument xmlDoc = new XmlDocument();
333             try
334             {
335                 xmlDoc.PreserveWhitespace = true;
336 
337                 xmlDoc.Load(path);
338             }
339             catch (Exception e)
340             {
341                 Console.WriteLine(e.Message);
342             }
343 
344             // Decrypt the "UserManagement" element.
345             EncryptXml.Decrypt(xmlDoc, tDESkey);
346             xmlDoc.Save(path);
347 
348             T serializableObject = null;
349 
350             using (TextReader textReader = CreateTextReader(isolatedStorageFolder, path))
351             {
352                 XmlSerializer xmlSerializer = CreateXmlSerializer(extraTypes);
353                 serializableObject = xmlSerializer.Deserialize(textReader) as T;
354             }
355 
356             EncryptXml.Encrypt(xmlDoc, "UserManagement", tDESkey);
357             xmlDoc.Save(path);
358 
359             return serializableObject;
360         }
361 
362         private static TextReader CreateTextReader(IsolatedStorageFile isolatedStorageFolder, string path)
363         {
364             TextReader textReader = null;
365 
366             if (isolatedStorageFolder == null)
367                 textReader = new StreamReader(path);
368             else
369                 textReader = new StreamReader(new IsolatedStorageFileStream(path, FileMode.Open, isolatedStorageFolder));
370 
371             return textReader;
372         }
373 
374         private static TextWriter CreateTextWriter(IsolatedStorageFile isolatedStorageFolder, string path)
375         {
376             TextWriter textWriter = null;
377 
378             if (isolatedStorageFolder == null)
379                 textWriter = new StreamWriter(path);
380             else
381                 textWriter = new StreamWriter(new IsolatedStorageFileStream(path, FileMode.OpenOrCreate, isolatedStorageFolder));
382 
383             return textWriter;
384         }
385 
386         private static XmlSerializer CreateXmlSerializer(System.Type[] extraTypes)
387         {
388             Type ObjectType = typeof(T);
389 
390             XmlSerializer xmlSerializer = null;
391 
392             if (extraTypes != null)
393                 xmlSerializer = new XmlSerializer(ObjectType, extraTypes);
394             else
395                 xmlSerializer = new XmlSerializer(ObjectType);
396 
397             return xmlSerializer;
398         }
399 
400         private static void SaveToDocumentFormat(T serializableObject, System.Type[] extraTypes, string path, IsolatedStorageFile isolatedStorageFolder, TripleDESCryptoServiceProvider tDESkey)
401         {
402             using (TextWriter textWriter = CreateTextWriter(isolatedStorageFolder, path))
403             {
404                 XmlSerializer xmlSerializer = CreateXmlSerializer(extraTypes);
405                 xmlSerializer.Serialize(textWriter, serializableObject);
406 
407                 textWriter.Close();
408 
409                 XmlDocument xmlDoc = new XmlDocument();
410                 try
411                 {
412                     xmlDoc.PreserveWhitespace = true;
413 
414                     xmlDoc.Load(path);
415                 }
416                 catch (Exception e)
417                 {
418                     Console.WriteLine(e.Message);
419                 }
420 
421                 EncryptXml.Encrypt(xmlDoc, "UserManagement", tDESkey);
422 
423                 xmlDoc.Save(path);
424             }
425         }
426 
427         private static void SaveToBinaryFormat(T serializableObject, string path, IsolatedStorageFile isolatedStorageFolder)
428         {
429             using (FileStream fileStream = CreateFileStream(isolatedStorageFolder, path))
430             {
431                 BinaryFormatter binaryFormatter = new BinaryFormatter();
432                 binaryFormatter.Serialize(fileStream, serializableObject);
433             }
434         }
435 
436         
437         #endregion
438     }
439 }

(3)Saving an object to an XML file/Loading an object from an XML file

// Load the userManagement object from the XML file using our UserAccountInfo class...
UserAccountInfo userManagement =ObjectXMLSerializer<UserAccountInfo>.Load(path, tDESkey);

// Load the userManagement object from the XML file using our userManagement class...
ObjectXMLSerializer<UserAccountInfo>.Save(usermanagement, XML_FILE_NAME, tDESkey);

 

方法二:

其实,要想仅仅实现xml的序列化和反序列化还是很简单的,作为常用的类,可以很简单地将其实现为公共类:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;

namespace XXX.Common
{
    public static class XmlHelper
    {
        public static object DeserializeObject<T>(string filePath)
        {
            try
            {
                var xs = new XmlSerializer(typeof(T));
                using (var fs = new FileStream(filePath, FileMode.Open))
                {
                    var reader = XmlReader.Create(fs);
                    return xs.Deserialize(reader);
                }
            }
            catch (Exception exp)
            {
                throw new XmlException($"Failed in XML Deserialization {filePath}", exp);
            }
        }

        public static void SerializeObject<T>(string filePath, T o)
        {
            try
            {
                var x = new XmlSerializer(typeof(T));
                using (var fs = new FileStream(filePath, FileMode.Create))
                {
                    var writer = XmlWriter.Create(fs);
                    x.Serialize(writer, o);
                }
            }
            catch (Exception exp)
            {
                throw new XmlException($"Failed in XML Serialization {filePath}", exp);
            }
        }
    }
}

  

 

 

另可参考文章:

1.XML序列化和反序列化

2.在.net中读写config文件的各种方法

 

posted @ 2017-05-17 23:34  小金乌会发光-Z&M  阅读(1079)  评论(0编辑  收藏  举报