文件和对象的转换
在写程序中经常会使用到配置文件,而且配置文件的内容通常还是要赋值给对象,那么每次如果都给一个特定的类去写一套读写肯定是很不方便,由于工作上的需求所以顺便写了一个通用的只要提供对象即可(ps:要保存的内容只能是基础类型,如果对象中有引用类型的将不会被保存,不过大部分配置文件的内容应该都是基础类型就OK了)
/// <summary>
/// 把对象转化为文件的内容
/// </summary>
public static class StreamClassToFile
{
/// <summary>
/// 每个对象的分隔
/// </summary>
private static string ClassLog = "`------------------------`" + RowEndLog;
/// <summary>
/// 单个对象的标志
/// </summary>
private static string SingleHandLog = "Single\n";
/// <summary>
/// 多个对象的标志
/// </summary>
private static string MoreleHandLog = "More\n";
/// <summary>
/// 分隔符
/// </summary>
private static string CenterLog = "|~|";
/// <summary>
/// 行结尾符
/// </summary>
private static string RowEndLog = "\n";
/// <summary>
/// 字段开始标识
/// </summary>
private static string FieldStartLog = "<|Fields>";
/// <summary>
/// 字段结束标识
/// </summary>
private static string FieldEndLog = "<Fields|>";
/// <summary>
/// 开始对象标识
/// </summary>
private static string ObjectStartLog = "<|Object>";
/// <summary>
/// 结束对象标识
/// </summary>
private static string ObjectEndLog = "<Object|>";
/// <summary>
/// 将对象保存到文件
/// </summary>
/// <param name="obj"></param>
public static void ObjectToFile(object obj, string fileName)
{
string saveString = SingleHandLog;
saveString += ObjectToString(obj);
using (Stream stream = new FileStream(fileName, FileMode.Create))
{
byte[] data = Encoding.UTF8.GetBytes(saveString);
stream.Write(data, 0, data.Length);
}
}
/// <summary>
/// 将对象转换为字符串
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
private static string ObjectToString(object obj)
{
StringBuilder saveString = new StringBuilder();
Type type = obj.GetType();
saveString.Append(ObjectStartLog);
saveString.Append(type.Name + RowEndLog);
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
///存储字段
saveString.Append(FieldStartLog + RowEndLog);
foreach (var item in fields)
{
if (IsBasisType(item.FieldType))
saveString.Append(item.FieldType.Name + CenterLog + item.Name + CenterLog + item.GetValue(obj).ToString() + CenterLog + RowEndLog);
}
saveString.Append(FieldEndLog + RowEndLog);
saveString.Append(ObjectEndLog);
return saveString.ToString();
}
/// <summary>
/// 将文件中的数据读取并且还原为一个对象(只支持有空构造函数的对象)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fileName"></param>
/// <returns></returns>
public static T FileToObject<T>(string fileName)
{
StringBuilder readString = new StringBuilder();
using (StreamReader stream = new StreamReader(fileName, Encoding.UTF8))
{
readString.Append(stream.ReadToEnd());
}
int logindex = readString.ToString().IndexOf(SingleHandLog);
if (logindex == -1 || logindex > SingleHandLog.Length)
{
return default(T);
}
return GetObjectByString<T>(readString.ToString());
}
/// <summary>
/// 根据类字符串组装类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="readString"></param>
/// <returns></returns>
private static T GetObjectByString<T>(string readString)
{
try
{
Type type = typeof(T);
//type.GetConstructor( BindingFlags.Public, new );
object readobj = Activator.CreateInstance(type);
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
ListData fieldsData = GetFieldValue(readString);///解析所有字段获取值
foreach (var item in fields)
{
if (IsBasisType(item.FieldType))
{
item.SetValue(readobj, GetValue(fieldsData[item.Name], item));
}
}
return (T)readobj;
}
catch (Exception ex)
{
return default(T);
}
}
/// <summary>
/// 检测是否是基础类型,只支持基础类型
/// </summary>
/// <param name="typeName">类型名</param>
/// <returns>true为是,false为否</returns>
public static bool IsBasisType(Type type)
{
if (type.IsPrimitive || type.Name == "string" || type.Name == "String" || type.Name == "Guid")
return true;
else
return false;
}
/// <summary>
/// 获取获取字段的数据
/// </summary>
/// <param name="info">字段信息</param>
/// <param name="file">总文件流</param>
/// <returns>值</returns>
private static ListData GetFieldValue(string file)
{
ListData data = new ListData();
string fieldstring = file.ToString();
int startIndex = fieldstring.IndexOf(FieldStartLog);
int endIndex = fieldstring.IndexOf(FieldEndLog);
fieldstring = fieldstring.Substring((startIndex + FieldStartLog.Length), (endIndex - startIndex - FieldStartLog.Length));
string[] fields = fieldstring.Split(RowEndLog.ToCharArray());
string[] values;
foreach (var item in fields)
{
values = item.Split(CenterLog.ToCharArray());
if (values.Length <= 1)
continue;
data.Add(values[CenterLog.Length], values[CenterLog.Length * 2]);
}
return data;
}
/// <summary>
/// 根据字段的类型变成对应的字段的值
/// </summary>
/// <param name="value">字段的值的字符串</param>
/// <param name="type">字段的类型</param>
/// <returns></returns>
private static object GetValue(string value, FieldInfo type)
{
try
{
TypeCode code = GetEnumTypeByString<TypeCode>(type.FieldType.Name);
if (code == TypeCode.Empty && type.FieldType.Name == "Guid")
return new Guid(value);
return Convert.ChangeType(value, code);
}
catch(Exception ex)
{
if(type.Name == "string")
{
return value;
}
else
{
return null;
}
}
}
/// <summary>
/// 批量读取
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="objs"></param>
/// <param name="fileName"></param>
public static List<T> FileToObjects<T>( string fileName)
{
StringBuilder readString = new StringBuilder();
using (StreamReader stream = new StreamReader(fileName, Encoding.UTF8))
{
readString.Append(stream.ReadToEnd());
}
int logindex = readString.ToString().IndexOf(MoreleHandLog);
if (logindex == -1 || logindex > MoreleHandLog.Length)
{
return default(List<T>);
}
List<T> objs = new List<T>();
////string[] classtrings = readString.ToString().Split(ClassLog.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
string[] classtrings = Regex.Split(readString.ToString(), ClassLog);
int index = 0;
foreach (string item in classtrings)
{
//if(index ++ % ClassLog.Length ==0 && index != classtrings.Length)
if(item.Length != 0)
objs.Add(GetObjectByString<T>(item));
}
return objs;
}
/// <summary>
/// 将多个对象保存到文件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="objs"></param>
/// <param name="fileName"></param>
public static void ObjectsToFile<T>(List<T> objs, string fileName)
{
StringBuilder saveStrings = new StringBuilder();
saveStrings.Append(MoreleHandLog);
foreach (object item in objs)
{
saveStrings.Append(ObjectToString(item));
saveStrings.Append(ClassLog);
}
using (Stream stream = new FileStream(fileName, FileMode.Create))
{
byte[] data = Encoding.UTF8.GetBytes(saveStrings.ToString());
stream.Write(data, 0, data.Length);
}
}
/// <summary>
/// 根据name检索对应枚举
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="name"></param>
/// <returns></returns>
public static T GetEnumTypeByString<T>(string name)
{
foreach (T item in Enum.GetValues(typeof(T)))
{
if(item.ToString() == name)
{
return item;
}
}
return default(T);
}
/// <summary>
/// 线性插值
/// </summary>
/// <param name="start">起始值</param>
/// <param name="end">终止值</param>
/// <param name="lerp">插值</param>
/// <returns></returns>
public static double Lerp(double start, double end, double lerp)
{
lerp = lerp < 0 ? 0 : lerp;
lerp = lerp > 1 ? 1 : lerp;
return (end + start) * lerp;
}
/// <summary>
/// 根据T类型的枚举的具体V类型的值获取对应的枚举值
/// </summary>
/// <typeparam name="T">枚举类型</typeparam>
/// <typeparam name="V">枚举类型继承的类型</typeparam>
/// <param name="value">对应的值</param>
/// <returns>对应的枚举值</returns>
public static T GetEnumTypeByType<T, V>(V value)
{
try
{
TypeCode code = GetEnumTypeByString<TypeCode>(value.GetType().Name);
foreach (T item in Enum.GetValues(typeof(T)))
{
if (Convert.ChangeType(value, code).Equals(value))
{
return item;
}
}
return default(T);
}
catch (Exception)
{
return default(T);
}
}
}
internal class ListData
{
/// <summary>
/// 数据
/// </summary>
private Dictionary<string, string> _data = new Dictionary<string, string>();
/// <summary>
/// 根据名称获取值
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public string this[string name]
{
get
{
if(_data.Keys.Contains(name))
{
return _data[name];
}
return "";
}
}
/// <summary>
/// 数据
/// </summary>
public Dictionary<string, string> Data
{
get
{
return _data;
}
}
/// <summary>
/// 添加一条数据
/// </summary>
/// <param name="name">属性名称</param>
/// <param name="value">属性的值</param>
public void Add(string name, string value)
{
_data.Add(name, value);
}
}
使用的时候只要调用StreamClassToFile.ObjectToFile(对象, 文件名称包含路径和名称);
同时还有ObjectsToFile支持List<T>类型的转化。
反向的是public static T FileToObject<T>(string fileName)
同样支持返回List<T>的对象组