关于序列化以及VS调试时默认的"相对路径"
同步自atpking.com
今天从龙头寺回来,也没什么事情,
就折腾下以前不是很搞的清楚的序列化和反序列化
去网上down了一个helper类,顺便逐句的写了下注释,
如果对Serialization 那块不是太熟悉的朋友可以看看
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
namespace ATPKING.Common
{
/// <summary>
/// 序列化相关操作助手
/// </summary>
public class SerializationHelper
{
private SerializationHelper()
{ }
/* 字典,用来存储XmlSerializer
* 注意是此处是static
* 实际上起缓存的作用
*/
private static Dictionary<int, XmlSerializer> serializer_dict = new Dictionary<int, XmlSerializer>();
/// <summary>
/// 为给予的类匹配一个XmlSerializer 对象,
/// 若之前就使用过,则从缓存里调出来,若没有,
/// 则新建一个对应的XmlSerializer 对象。
/// </summary>
/// <param name="t">给予的类</param>
/// <returns></returns>
public static XmlSerializer GetSerializer(Type t)
{
//先获得type 的哈希值,作为字典的索引
int type_hash = t.GetHashCode();
//如果字典里没有这个type的哈希,就创建一个,放到字典表里
if (!serializer_dict.ContainsKey(type_hash))
serializer_dict.Add(type_hash, new XmlSerializer(t));
//查询到这个哈希对应的对象,传出去
return serializer_dict[type_hash];
}
/// <summary>
/// 反序列化
/// </summary>
/// <param name="type">对象类型</param>
/// <param name="filename">文件路径</param>
/// <returns></returns>
public static object Load(Type type, string filename)
{
FileStream fs = null;
try
{
/* 打开一个文件流,注意最后一个参数 FileShare
* 意思为这个文件在打开,未关闭的时候,
* 其他程序(进程、线程等)也可以打开此文件,且可以写入此文件
*/
fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
/*
* 此处为根据type,生成一个Serializer对象
* 此对象用来 根据文件流(FileStream)里的xml文件
* 生成一个object对象
* 注意,FileStream中的xml实际上是Type对应的对象的属性的值
* 否则会抛出异常.
*/
XmlSerializer serializer = new XmlSerializer(type);
//反序列化
return serializer.Deserialize(fs);
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (fs != null)
fs.Close();
}
}
/// <summary>
/// 序列化
/// </summary>
/// <param name="obj">对象</param>
/// <param name="filename">文件路径</param>
public static bool Save(object obj, string filename)
{
bool success = false;
FileStream fs = null;
// serialize it...
try
{
/*
* 建立文件流
* param1 路径
* param2 文件打开方式,创建一个文件,若有,则覆盖创建文件
* param3 设置访问权限,为写权限
* param4 文件在操作时候是否允许其他程序(进程,线程等)操作, 可读可写
*/
fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
//生成一个对象对应的类的一个XmlSerializer 对象
XmlSerializer serializer = new XmlSerializer(obj.GetType());
//序列化这个对象,并将结果放在文件流中
serializer.Serialize(fs, obj);
//要是一切顺利,返回true
success = true;
}
catch (Exception ex)
{
throw ex;
}
finally//不管怎样,关闭文件流.
{
if (fs != null)
fs.Close();
}
return success;
}
/// <summary>
/// xml序列化成字符串
/// </summary>
/// <param name="obj">对象</param>
/// <returns>xml字符串</returns>
public static string Serialize(object obj)
{
string returnStr = "";
XmlSerializer serializer = GetSerializer(obj.GetType());
// 实例化一个内存流
MemoryStream ms = new MemoryStream();
XmlTextWriter xtw = null;
StreamReader sr = null;
try
{
//实例化一个xml的写对象,其中使用utf-8 编码,写入到刚实例化的内存流中去
xtw = new System.Xml.XmlTextWriter(ms, Encoding.UTF8);
//设置缩进方式
xtw.Formatting = System.Xml.Formatting.Indented;
//序列化它
serializer.Serialize(xtw, obj);
/*
* 此时内存流已经指向写完的地方,
* 要再次读取到这个内存里的内容,
* 需要将其"指针"指向内存流的开始
* 下面一句就是做这个事情
* param1 针对param2 的偏移量,
* param2 内存开始的地方
*/
ms.Seek(0, SeekOrigin.Begin);
//实例化一个流阅读器,去读内存流
sr = new StreamReader(ms);
returnStr = sr.ReadToEnd();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (xtw != null)
xtw.Close();
if (sr != null)
sr.Close();
ms.Close();
}
return returnStr;
}
/// <summary>
/// 反序列化 ,通过一个string
/// </summary>
/// <param name="type">反序列化的类的类型</param>
/// <param name="s">序列源</param>
/// <returns></returns>
public static object DeSerialize(Type type, string s)
{
/*
* 此处将字符串转化为byte数组
* 其中值得注意的是,使用UTF-8 编码
* 就可以回避因为是非ASCII码被解析成乱码了
*/
byte[] b = System.Text.Encoding.UTF8.GetBytes(s);
try
{
XmlSerializer serializer = GetSerializer(type);
return serializer.Deserialize(new MemoryStream(b));
}
catch (Exception ex)
{
throw ex;
}
}
}
}
另外在调试的时候
如果说填写的是相对路径而不是绝对路径的话
生成的文件就会在vs 所安装的目录之下,而不是项目本身的目录
(比如我的,就生成在D:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE 下)