Unity数据持久化4——2进制
概述
基础知识
各类型数据转字节数据
文件操作相关
文件相关
文件流相关
文件夹相关
练习题
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
public class Exercises1 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
//Student s = new Student();
//s.age = 18;
//s.name = "Sunset";
//s.number = 1;
//s.sex = true;
//s.Save("学生信息");
Student s2 = Student.Load("学生信息");
}
// Update is called once per frame
void Update()
{
}
}
public class Student
{
public int age;
public string name;
public int number;
public bool sex;
public void Save(string fileName)
{
Debug.Log(Application.persistentDataPath);
//如果不存在指定路径 则创建一个文件夹
if( !Directory.Exists(Application.persistentDataPath + "/Student"))
{
Directory.CreateDirectory(Application.persistentDataPath + "/Student");
}
//新建一个指定名字的文件 并且返回 文件流 进行字节的存储
using (FileStream fs = new FileStream(Application.persistentDataPath + "/Student/" + fileName + ".set", FileMode.OpenOrCreate, FileAccess.Write))
{
//先写 age
byte[] bytes = BitConverter.GetBytes(age);
fs.Write(bytes, 0, bytes.Length);
//写 name (先存这个字节的长度,再存字节内容)
bytes = Encoding.UTF8.GetBytes(name);
//存储字符串字节数组的长度
fs.Write(BitConverter.GetBytes(bytes.Length), 0, 4);
fs.Write(bytes, 0, bytes.Length);
//写 number
bytes = BitConverter.GetBytes(number);
fs.Write(bytes, 0, bytes.Length);
//写 sex
bytes = BitConverter.GetBytes(sex);
fs.Write(bytes, 0, bytes.Length);
//一定记住
fs.Flush();
fs.Dispose();
}
}
public static Student Load(string fileName)
{
//判断文件是否存在
if (!File.Exists(Application.persistentDataPath + "/Student/" + fileName + ".set"))
{
Debug.LogWarning("没有找到对于文件");
return null;
}
//申明对象
Student s = new Student();
//加载2进制文件 进行赋值
using(FileStream fs = File.Open(Application.persistentDataPath + "/Student/" + fileName + ".set", FileMode.Open, FileAccess.Read))
{
//把我们文件中的字节 全部读取出来
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, bytes.Length);
fs.Close(); //Dispose 就可以不用调用了 因为 usin会帮我们调用一次
int index = 0;
//挨个读取其中的内容
//先读 age
s.age = BitConverter.ToInt32(bytes, index);
index += 4;
//读 name
//先读字符串字节数组的长度
int length = BitConverter.ToInt32(bytes, index);
index += 4;
s.name = Encoding.UTF8.GetString(bytes, index, length);
index += length;
//读 number
s.number = BitConverter.ToInt32(bytes, index);
index += 4;
//读 sex
s.sex = BitConverter.ToBoolean(bytes, index);
index += 1;
}
return s;
}
}
C#类对象的序列化和反序列化
序列化
反序列化
加密
练习
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;
public class BinaryDataMgr
{
private static BinaryDataMgr instance = new BinaryDataMgr();
public static BinaryDataMgr Instance => instance;
private static string SAVE_PATH = Application.persistentDataPath + "/Data/";
private BinaryDataMgr()
{
}
/// <summary>
/// 存储类对象数据
/// </summary>
/// <param name="obj"></param>
/// <param name="fileName"></param>
public void Save(object obj, string fileName)
{
//先判断路径文件夹是否存在
if (!Directory.Exists(SAVE_PATH))
Directory.CreateDirectory(SAVE_PATH);
using (FileStream fs = new FileStream(SAVE_PATH + fileName + ".set", FileMode.OpenOrCreate, FileAccess.Write))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, obj);
fs.Close();
}
}
/// <summary>
/// 读取2进制数据转换成对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fileNmae"></param>
/// <returns></returns>
public T Load<T>(string fileName) where T : class
{
//如果不存在这个文件 就直接返回泛型对象的默认值
if (!File.Exists(SAVE_PATH + fileName + ".set"))
return default(T);
T obj;
using(FileStream fs = File.Open(SAVE_PATH + fileName + ".set", FileMode.Open, FileAccess.Read))
{
BinaryFormatter bf = new BinaryFormatter();
obj = bf.Deserialize(fs) as T;
fs.Close();
}
return obj;
}
}
总结
实践小项目
知识点补充
Unity中添加菜单栏功能
Excel数据读取
导入Excel相关Dll包
Excel数据读取
需求分析
Excel配置表数据功能
制定配置表规则
分别空出一行来表示数据类型
空出一行标明 唯一ID(用于字典的Key)
空出一行 作为描述信息
读取Excel目录下所有Excel文件
生成数据结构类
using Excel;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using UnityEditor;
using UnityEngine;
public class ExcelTool
{
/// <summary>
/// excel 文件存放的路径
/// </summary>
public static string EXCEL_PATH = Application.dataPath + "/ArtRes/Excel/";
/// <summary>
/// 数据结构类脚本存储位置路径
/// </summary>
public static string DATA_CLASS_PATH = Application.dataPath + "/Scripts/ExcelData/DataClass";
[MenuItem("GameTool/GenerateExcel")]
private static void GenerateExcel()
{
//记录指定路径中的所有Excel文件 用于生成对应的3个文件
DirectoryInfo dInfo = Directory.CreateDirectory(EXCEL_PATH);
//得到指定路径中的所有文件信息 相当于就是得到所有的Excel表
FileInfo[] files = dInfo.GetFiles();
//数据表容器
DataTableCollection tableConllection;
for (int i = 0; i < files.Length; i++)
{
//如果不是excel 文件就不用处理了
if (files[i].Extension != ".xlsx" && files[i].Extension != ".xls")
continue;
//Debug.Log(files[i].Name);
//打开一个Excel文件得到其中的所有表的数据
using (FileStream fs = files[i].Open(FileMode.Open, FileAccess.Read))
{
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(fs);
tableConllection = excelReader.AsDataSet().Tables;
fs.Close();
}
//遍历文件中的所有表的信息
foreach (DataTable table in tableConllection)
{
Debug.Log(table.TableName);
//生成数据结构类
GenerateExcelDataClass(table);
//生成容器类
//生成2进制数据
}
}
}
/// <summary>
/// 生成Excel表对应的数据结构类
/// </summary>
/// <param name="table"></param>
private static void GenerateExcelDataClass(DataTable table)
{
//字段名行
DataRow rowName = GetVariableNameRow(table);
//字段类型行
DataRow rowType = GetVariableTypeRow(table);
//判断路径是否存在 没有的话 就创建文件夹
if (!Directory.Exists(DATA_CLASS_PATH))
Directory.CreateDirectory(DATA_CLASS_PATH);
//如果我们要生成对应的数据结构类脚本 其实就是通过代码进行字符串拼接 然后存进文件就行了
string str = "public class " + table.TableName + "\n{\n";
//变量进行字符串拼接
for (int i = 0; i < table.Columns.Count; i++)
{
str += " public " + rowType[i].ToString() + " " + rowName[i].ToString() + ";\n";
}
str += "}";
//把拼接好的字符串存到指定文件中去
File.WriteAllText(DATA_CLASS_PATH + table.TableName + ".cs", str);
//刷新 Project 窗口
AssetDatabase.Refresh();
}
/// <summary>
/// 获取变量名所在的行 方便以后修改
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
private static DataRow GetVariableNameRow(DataTable table)
{
return table.Rows[0];
}
/// <summary>
/// 获取变量类型所在行 方便以后修改
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
private static DataRow GetVariableTypeRow(DataTable table)
{
return table.Rows[1];
}
}
生成表容器类
using Excel;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using UnityEditor;
using UnityEngine;
public class ExcelTool
{
/// <summary>
/// excel 文件存放的路径
/// </summary>
public static string EXCEL_PATH = Application.dataPath + "/ArtRes/Excel/";
/// <summary>
/// 数据结构类脚本存储位置路径
/// </summary>
public static string DATA_CLASS_PATH = Application.dataPath + "/Scripts/ExcelData/DataClass/";
/// <summary>
/// 容器类脚本存储位置路径
/// </summary>
public static string DATA_CONTAINER_PATH = Application.dataPath + "/Scripts/ExcelData/Container/";
[MenuItem("GameTool/GenerateExcel")]
private static void GenerateExcel()
{
//记录指定路径中的所有Excel文件 用于生成对应的3个文件
DirectoryInfo dInfo = Directory.CreateDirectory(EXCEL_PATH);
//得到指定路径中的所有文件信息 相当于就是得到所有的Excel表
FileInfo[] files = dInfo.GetFiles();
//数据表容器
DataTableCollection tableConllection;
for (int i = 0; i < files.Length; i++)
{
//如果不是excel 文件就不用处理了
if (files[i].Extension != ".xlsx" && files[i].Extension != ".xls")
continue;
//Debug.Log(files[i].Name);
//打开一个Excel文件得到其中的所有表的数据
using (FileStream fs = files[i].Open(FileMode.Open, FileAccess.Read))
{
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(fs);
tableConllection = excelReader.AsDataSet().Tables;
fs.Close();
}
//遍历文件中的所有表的信息
foreach (DataTable table in tableConllection)
{
Debug.Log(table.TableName);
//生成数据结构类
GenerateExcelDataClass(table);
//生成容器类
GenerateExcelContainer(table);
//生成2进制数据
}
}
}
/// <summary>
/// 生成Excel表对应的数据结构类
/// </summary>
/// <param name="table"></param>
private static void GenerateExcelDataClass(DataTable table)
{
//字段名行
DataRow rowName = GetVariableNameRow(table);
//字段类型行
DataRow rowType = GetVariableTypeRow(table);
//判断路径是否存在 没有的话 就创建文件夹
if (!Directory.Exists(DATA_CLASS_PATH))
Directory.CreateDirectory(DATA_CLASS_PATH);
//如果我们要生成对应的数据结构类脚本 其实就是通过代码进行字符串拼接 然后存进文件就行了
string str = "public class " + table.TableName + "\n{\n";
//变量进行字符串拼接
for (int i = 0; i < table.Columns.Count; i++)
{
str += " public " + rowType[i].ToString() + " " + rowName[i].ToString() + ";\n";
}
str += "}";
//把拼接好的字符串存到指定文件中去
File.WriteAllText(DATA_CLASS_PATH + table.TableName + ".cs", str);
//刷新 Project 窗口
AssetDatabase.Refresh();
}
/// <summary>
/// 获取变量名所在的行 方便以后修改
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
private static DataRow GetVariableNameRow(DataTable table)
{
return table.Rows[0];
}
/// <summary>
/// 获取变量类型所在行 方便以后修改
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
private static DataRow GetVariableTypeRow(DataTable table)
{
return table.Rows[1];
}
/// <summary>
/// 生成Excel表对应的数据容器类
/// </summary>
/// <param name="table"></param>
private static void GenerateExcelContainer(DataTable table)
{
//得到主键索引
int keyIndex = GetKeyIndex(table);
//得到字段类型行
DataRow rowType = GetVariableTypeRow(table);
//没有路径就创建该路径
if (!Directory.Exists(DATA_CONTAINER_PATH))
Directory.CreateDirectory(DATA_CONTAINER_PATH);
//进行拼接
string str = "using System.Collections.Generic;\n";
str += "public class " + table.TableName + "Container" + "\n{\n";
str += " ";
str += "public Dictionary<" + rowType[keyIndex].ToString() + ", " + table.TableName + "> ";
str += "dataDic = new " + "Dictionary<" + rowType[keyIndex].ToString() + ", " + table.TableName + ">();\n";
str += "}";
//写入文件
File.WriteAllText(DATA_CONTAINER_PATH + table.TableName + "Container.cs", str);
//刷新Project窗口
AssetDatabase.Refresh();
}
/// <summary>
/// 获取主键索引
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
private static int GetKeyIndex(DataTable table)
{
DataRow row = table.Rows[2];
for (int i = 0; i < table.Columns.Count; i++)
{
//得到 key的那一列
if (row[i].ToString() == "key")
return i;
}
//如果没有设置 就传回0
return 0;
}
}
生成Excel 2进制数据
using Excel;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
public class ExcelTool
{
/// <summary>
/// excel 文件存放的路径
/// </summary>
public static string EXCEL_PATH = Application.dataPath + "/ArtRes/Excel/";
/// <summary>
/// 数据结构类脚本存储位置路径
/// </summary>
public static string DATA_CLASS_PATH = Application.dataPath + "/Scripts/ExcelData/DataClass/";
/// <summary>
/// 容器类脚本存储位置路径
/// </summary>
public static string DATA_CONTAINER_PATH = Application.dataPath + "/Scripts/ExcelData/Container/";
/// <summary>
/// 2进制数据存储位置路径
/// </summary>
public static string DATA_BINARY_PATH = Application.streamingAssetsPath + "/Binary/";
/// <summary>
/// 真正内容开始的行号
/// </summary>
public static int BEGIN_INDEX = 4;
[MenuItem("GameTool/GenerateExcel")]
private static void GenerateExcel()
{
//记录指定路径中的所有Excel文件 用于生成对应的3个文件
DirectoryInfo dInfo = Directory.CreateDirectory(EXCEL_PATH);
//得到指定路径中的所有文件信息 相当于就是得到所有的Excel表
FileInfo[] files = dInfo.GetFiles();
//数据表容器
DataTableCollection tableConllection;
for (int i = 0; i < files.Length; i++)
{
//如果不是excel 文件就不用处理了
if (files[i].Extension != ".xlsx" && files[i].Extension != ".xls")
continue;
//Debug.Log(files[i].Name);
//打开一个Excel文件得到其中的所有表的数据
using (FileStream fs = files[i].Open(FileMode.Open, FileAccess.Read))
{
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(fs);
tableConllection = excelReader.AsDataSet().Tables;
fs.Close();
}
//遍历文件中的所有表的信息
foreach (DataTable table in tableConllection)
{
Debug.Log(table.TableName);
//生成数据结构类
GenerateExcelDataClass(table);
//生成容器类
GenerateExcelContainer(table);
//生成2进制数据
GenerateExcelBinary(table);
}
}
}
/// <summary>
/// 生成Excel表对应的数据结构类
/// </summary>
/// <param name="table"></param>
private static void GenerateExcelDataClass(DataTable table)
{
//字段名行
DataRow rowName = GetVariableNameRow(table);
//字段类型行
DataRow rowType = GetVariableTypeRow(table);
//判断路径是否存在 没有的话 就创建文件夹
if (!Directory.Exists(DATA_CLASS_PATH))
Directory.CreateDirectory(DATA_CLASS_PATH);
//如果我们要生成对应的数据结构类脚本 其实就是通过代码进行字符串拼接 然后存进文件就行了
string str = "public class " + table.TableName + "\n{\n";
//变量进行字符串拼接
for (int i = 0; i < table.Columns.Count; i++)
{
str += " public " + rowType[i].ToString() + " " + rowName[i].ToString() + ";\n";
}
str += "}";
//把拼接好的字符串存到指定文件中去
File.WriteAllText(DATA_CLASS_PATH + table.TableName + ".cs", str);
//刷新 Project 窗口
AssetDatabase.Refresh();
}
/// <summary>
/// 获取变量名所在的行 方便以后修改
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
private static DataRow GetVariableNameRow(DataTable table)
{
return table.Rows[0];
}
/// <summary>
/// 获取变量类型所在行 方便以后修改
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
private static DataRow GetVariableTypeRow(DataTable table)
{
return table.Rows[1];
}
/// <summary>
/// 生成Excel表对应的数据容器类
/// </summary>
/// <param name="table"></param>
private static void GenerateExcelContainer(DataTable table)
{
//得到主键索引
int keyIndex = GetKeyIndex(table);
//得到字段类型行
DataRow rowType = GetVariableTypeRow(table);
//没有路径就创建该路径
if (!Directory.Exists(DATA_CONTAINER_PATH))
Directory.CreateDirectory(DATA_CONTAINER_PATH);
//进行拼接
string str = "using System.Collections.Generic;\n";
str += "public class " + table.TableName + "Container" + "\n{\n";
str += " ";
str += "public Dictionary<" + rowType[keyIndex].ToString() + ", " + table.TableName + "> ";
str += "dataDic = new " + "Dictionary<" + rowType[keyIndex].ToString() + ", " + table.TableName + ">();\n";
str += "}";
//写入文件
File.WriteAllText(DATA_CONTAINER_PATH + table.TableName + "Container.cs", str);
//刷新Project窗口
AssetDatabase.Refresh();
}
/// <summary>
/// 获取主键索引
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
private static int GetKeyIndex(DataTable table)
{
DataRow row = table.Rows[2];
for (int i = 0; i < table.Columns.Count; i++)
{
//得到 key的那一列
if (row[i].ToString() == "key")
return i;
}
//如果没有设置 就传回0
return 0;
}
/// <summary>
/// 生成excel 2进制数据
/// </summary>
/// <param name="table"></param>
private static void GenerateExcelBinary(DataTable table)
{
// 判断路径是否存在, 不存在就创建
if (!Directory.Exists(DATA_BINARY_PATH))
Directory.CreateDirectory(DATA_BINARY_PATH);
//创建一个2进制文件进行写入
using(FileStream fs = new FileStream(DATA_BINARY_PATH + table.TableName + ".set", FileMode.OpenOrCreate, FileAccess.Write))
{
//存储具体的excel对应的2进制信息
//1.先要存储我们需要写多少行的数据 方便我们读取
// - 4 的原因是因为 前面4行是配置规则 并不是我们需要记录的数据内容
fs.Write(BitConverter.GetBytes(table.Rows.Count - 4), 0, 4);
//2.存储主键的变量名
string keyName = GetVariableNameRow(table)[GetKeyIndex(table)].ToString();
byte[] bytes = Encoding.UTF8.GetBytes(keyName);
//存储字符串字节数组的长度
fs.Write(BitConverter.GetBytes(bytes.Length), 0, 4);
//存储字符串字节数组
fs.Write(bytes, 0, bytes.Length);
//遍历所有内容的行 进行2进制的写入
DataRow row;
//得到类型行 根据类型来决定应该如何写入数据
DataRow rowType = GetVariableTypeRow(table);
for (int i = BEGIN_INDEX; i < table.Rows.Count; i++)
{
//得到一行的数据
row = table.Rows[i];
for (int j = 0; j < table.Columns.Count; j++)
{
switch (rowType[j].ToString())
{
case "int":
fs.Write(BitConverter.GetBytes(int.Parse(row[j].ToString())), 0, 4);
break;
case "float":
fs.Write(BitConverter.GetBytes(float.Parse(row[j].ToString())), 0, 4);
break;
case "bool":
fs.Write(BitConverter.GetBytes(bool.Parse(row[j].ToString())), 0, 1);
break;
case "string":
bytes = Encoding.UTF8.GetBytes(row[j].ToString());
//写入字符串字节数组的长度
fs.Write(BitConverter.GetBytes(bytes.Length), 0, 4);
//写入字符串字节数组
fs.Write(bytes, 0, bytes.Length);
break;
}
}
}
fs.Close();
}
//属性 Project 窗口
AssetDatabase.Refresh();
}
}
表加载使用功能
在 BinaryDataMgr 的基础上进行修改
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using UnityEngine;
public class BinaryDataMgr
{
private static BinaryDataMgr instance = new BinaryDataMgr();
public static BinaryDataMgr Instance => instance;
/// <summary>
/// 用于存储所有Excel表数据的容器
/// </summary>
private Dictionary<string, object> tableDic = new Dictionary<string, object>();
/// <summary>
/// 数据存储的位置
/// </summary>
private static string SAVE_PATH = Application.persistentDataPath + "/Data/";
/// <summary>
/// 2进制数据存储位置路径
/// </summary>
public static string DATA_BINARY_PATH = Application.streamingAssetsPath + "/Binary/";
private BinaryDataMgr()
{
}
public void InitData()
{
//LoadTable<TowerInfoContainer, TowerInfo>();
//LoadTable<PlayerInfoContainer, PlayerInfo>();
//LoadTable<TestInfoContainer, TestInfo>();
}
/// <summary>
/// 加载Excel 表的2进制数据到内存中
/// </summary>
/// <typeparam name="T">容器类名</typeparam>
/// <typeparam name="K">数据结构类类名</typeparam>
public void LoadTable<T, K>()
{
//读取 excel表对应的2进制文件 来进行解析
using (FileStream fs = File.Open(DATA_BINARY_PATH + typeof(K).Name + ".set", FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, bytes.Length);
fs.Close();
//用于记录当前读取了多少个字节
int index = 0;
//读取多少行数据
int count = BitConverter.ToInt32(bytes, index);
index += 4;
//读取主键的名字
int keyNameLength = BitConverter.ToInt32(bytes, index);
index += 4;
string keyName = Encoding.UTF8.GetString(bytes, index, keyNameLength);
index += keyNameLength;
//创建容器类对象
Type contaninerType = typeof(T);
object contaninerObj = Activator.CreateInstance(contaninerType);
//得到数据结构类的Type
Type classType = typeof(K);
//通过反射 得到数据结构类 所有字段的信息
FieldInfo[] infos = classType.GetFields();
//读取每一行的信息
for (int i = 0; i < count; i++)
{
//实例化一个数据结构类 对象
object dataObj = Activator.CreateInstance(classType);
foreach (FieldInfo info in infos)
{
if(info.FieldType == typeof(int))
{
//相当于就是把2进制数据转为int 然后赋值给了对应的字段
info.SetValue(dataObj, BitConverter.ToInt32(bytes, index));
index += 4;
}
else if(info.FieldType == typeof(float))
{
info.SetValue(dataObj, BitConverter.ToSingle(bytes, index));
index += 4;
}
else if (info.FieldType == typeof(bool))
{
info.SetValue(dataObj, BitConverter.ToBoolean(bytes, index));
index += 1;
}
else if (info.FieldType == typeof(string))
{
//读取字符串数组长度
int length = BitConverter.ToInt32(bytes, index);
index += 4;
info.SetValue(dataObj, Encoding.UTF8.GetString(bytes, index, length));
index += length;
}
}
//读取完一行的数据 就应该把这个数据添加到容器对象中
//得到容器对象中的 字典对象
object dicObject = contaninerType.GetField("dataDic").GetValue(contaninerObj);
//通过字典对象得到其中的 Add 方法
MethodInfo mInfo = dicObject.GetType().GetMethod("Add");
//得到数据结构类对象中 指定主键字段的值
object keyValue = classType.GetField(keyName).GetValue(dataObj);
mInfo.Invoke(dicObject, new object[] { keyValue, dataObj});
}
//把读取完的表记录下来
tableDic.Add(typeof(T).Name, contaninerObj);
//fs.Close();
}
}
/// <summary>
/// 得到一张表的信息
/// </summary>
/// <typeparam name="T">容器类名</typeparam>
/// <returns></returns>
public T GetTable<T>() where T:class
{
string tableName = typeof(T).Name;
if (tableDic.ContainsKey(tableName))
return tableDic[tableName] as T;
return null;
}
/// <summary>
/// 存储类对象数据
/// </summary>
/// <param name="obj"></param>
/// <param name="fileName"></param>
public void Save(object obj, string fileName)
{
//先判断路径文件夹是否存在
if (!Directory.Exists(SAVE_PATH))
Directory.CreateDirectory(SAVE_PATH);
using (FileStream fs = new FileStream(SAVE_PATH + fileName + ".set", FileMode.OpenOrCreate, FileAccess.Write))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, obj);
fs.Close();
}
}
/// <summary>
/// 读取2进制数据转换成对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fileNmae"></param>
/// <returns></returns>
public T Load<T>(string fileName) where T : class
{
//如果不存在这个文件 就直接返回泛型对象的默认值
if (!File.Exists(SAVE_PATH + fileName + ".set"))
return default(T);
T obj;
using(FileStream fs = File.Open(SAVE_PATH + fileName + ".set", FileMode.Open, FileAccess.Read))
{
BinaryFormatter bf = new BinaryFormatter();
obj = bf.Deserialize(fs) as T;
fs.Close();
}
return obj;
}
}
注:这段代码遗留了个报错,暂时没能解决!!!
注:报错原因找到了,在配置Excel数据表格时一定不要手贱多打空格,多打的话二进制编译时会编译进去,然后读写出来时一些索引就会出问题!!!
(我是因为这个int后面加了个空格,导致string读取长度时读出一亿多的字符串长度,服啦!)