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; /// <summary> /// 二进制文件管理类 /// 电脑端逻辑 ,webgl不适用读取 /// BitConverter.GetBytes Encoding.UTF8.GetBytes /// 序列化自定义类 需要加特性 [System.Serializable] /// </summary> public class BinaryManager : BaseManager<BinaryManager> { private BinaryManager() { InitData(); } /// <summary> /// 文件默认存储路径 /// </summary> private static readonly string SavePath = Application.persistentDataPath + "/Data/"; /// <summary> /// 二进制数据 /// </summary> public static string BinaryDataPath = Application.streamingAssetsPath + "/BinaryData/"; /// <summary> /// 用于存储所有表 /// </summary> private readonly Dictionary<string, object> tableDic = new Dictionary<string, object>(); /// <summary> /// 加载二进制配置表数据 /// </summary> public void InitData() { LoadTable<TB_SchemeContainer, TB_Scheme>(); LoadTable<TB_ProcessContainer, TB_Process>(); LoadTable<TB_SubProcessContainer, TB_SubProcess>(); LoadTable<TB_SubProcessStepContainer, TB_SubProcessStep>(); LoadTable<TB_SystemContainer, TB_System>(); LoadTable<TB_DeviceTypeContainer, TB_DeviceType>(); LoadTable<TB_ToolAndMaterialContainer, TB_ToolAndMaterial>(); } /// <summary> /// 加载Excel表的2进制数据到内存中 /// </summary> /// <typeparam name="T">容器类名</typeparam> /// <typeparam name="K">数据结构类名</typeparam> private void LoadTable<T, K>() { //读取二进制文件 解析 using FileStream fs = File.Open(BinaryManager.BinaryDataPath + typeof(K).Name + ".binary", FileMode.Open, FileAccess.Read); byte[] data = new byte[fs.Length]; fs.Read(data, 0, data.Length); fs.Close(); int index = 0; //读取多少行 int count = BitConverter.ToInt32(data, index); index += 4; //读取主键变量名 字符串长度 int keyNameLength = BitConverter.ToInt32(data, index); index += 4; //读取主键变量名 string keyName = Encoding.UTF8.GetString(data, 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 fi in infos) { if (fi.FieldType == typeof(int)) { //将2进制数据转为int 然后给对应字段赋值 fi.SetValue(dataObj, BitConverter.ToInt32(data, index)); index += 4; } else if (fi.FieldType == typeof(bool)) { //将2进制数据转为int 然后给对应字段赋值 fi.SetValue(dataObj, BitConverter.ToBoolean(data, index)); index += 1; } else if (fi.FieldType == typeof(float)) { //将2进制数据转为int 然后给对应字段赋值 fi.SetValue(dataObj, BitConverter.ToSingle(data, index)); index += 4; } else if (fi.FieldType == typeof(string)) { int length = BitConverter.ToInt32(data, index); index += 4; fi.SetValue(dataObj, Encoding.UTF8.GetString(data, index, length)); index += length; } } //读取完一行的数据了 应该把这个数据添加到容器对象中 //得到容器对象中的 字典对象 object dicObj = contaninerType.GetField("dataDic").GetValue(contaninerObj); //通过字典对象得到其中的Add方法 MethodInfo methodInfo = dicObj.GetType().GetMethod("Add"); // object keyValue = classType.GetField(keyName).GetValue(dataObj); //Debug.Log(keyValue); methodInfo.Invoke(dicObj, new object[] { keyValue, dataObj }); } //把读取完的表记录下来 tableDic.Add(typeof(T).Name, contaninerObj); } /// <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="data"></param> /// <param name="fileName"></param> public void SaveData(object data, string fileName) { if (!Directory.Exists(SavePath)) Directory.CreateDirectory(SavePath); using FileStream fs = new FileStream(SavePath + fileName + ".binary", FileMode.OpenOrCreate, FileAccess.Write); BinaryFormatter binaryFormatter = new BinaryFormatter(); binaryFormatter.Serialize(fs, data); fs.Flush(); fs.Close(); fs.Dispose(); } /// <summary> /// 读取数据 返回 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="fileName"></param> /// <returns></returns> public T LoadData<T>(string fileName)where T : class,new() { if (!File.Exists(SavePath + fileName + ".binary")) { return default; } T data = new T(); using (FileStream fs = File.Open(SavePath + fileName + ".binary",FileMode.Open,FileAccess.Read)) { BinaryFormatter binaryFormatter =new BinaryFormatter(); data = binaryFormatter.Deserialize(fs) as T; fs.Close(); fs.Dispose(); } return data; } }