二进制持久化

1.字符串和其他类型转字节类型 BitConverter和Encoding

2.文件流的操作

  //文件流操作
        //打开或创建指定文件
        FileStream fs = File.Open(Application.dataPath + "/Unity3.cl", FileMode.OpenOrCreate, FileAccess.ReadWrite);
        //重要属性和方法
        print(fs.Length);
        if(fs.CanRead)
        {

        }
        else if(fs.CanWrite)
        {

        }
        //将文件写入
        fs.Flush();
        //关闭流
        fs.Close();
        //缓存资源的回收
        fs.Dispose();

        //写入字节
        FileStream fs2 = new FileStream(Application.dataPath + "/Untitycl.ccc", FileMode.OpenOrCreate, FileAccess.ReadWrite);
        //写入整形 转字节
        byte[] bytes = BitConverter.GetBytes(999);
        fs2.Write(bytes, 0, 4);
        //写入字符串 转字节
        byte[] bytes1 = Encoding.UTF8.GetBytes("唐老师哈哈哈哈");
        //先写入字符串的长度 整形转字节
        fs2.Write(BitConverter.GetBytes(bytes1.Length), 0, 4);
        //再写入字符串
        fs2.Write(bytes1,0,bytes1.Length);
        //!!!!
        //文件写入
        fs2.Flush();
        //缓存资源的回收
        fs2.Dispose();
        //读取字节
        FileStream fs3 = new FileStream(Application.dataPath + "/Untitycl.ccc", FileMode.OpenOrCreate, FileAccess.ReadWrite);
        //声明一个四字节的字节数组
        byte[] bytes2 = new byte[4];
        //记录流的下标状态
        int index = fs3.Read(bytes2, 0, 4);
        //读整形  字节转整形
        int res3 = BitConverter.ToInt32(bytes2, 0);
        print("流前进了" + index + "个位置");
        print("读取的整数为:" + res3);
        
        //读字符串长度(整形)
        index= fs3.Read(bytes2, 0, 4);
        print("流在4,前进了" + index + "个位置");
        int length=BitConverter.ToInt32(bytes2, 0);
        //声明一个字符串大小的字节数组
        byte[] bytes3 = new byte[length];
        index=fs3.Read(bytes3,0,length);
        print("流在8,前进了" + index + "个位置");
        //读字符串
        string s =Encoding.UTF8.GetString(bytes3);

流的索引 index 

3.文件夹操作

    if(Directory.Exists(Application.dataPath+"/二进制操作"))
        {
            print("文件夹存在");
        }
       else
        {
            print("文件夹不存在");
        }
        Directory.CreateDirectory(Application.dataPath + "/二进制操作");
        //删除文件夹
        //Directory.Delete(Application.dataPath + "/二进制操作",true);
        //得到指定路径的文件 夹 名
     string []str=  Directory.GetDirectories(Application.dataPath);
        for (int i = 0; i < str.Length; i++)
        {
            print(str[i]);
        }
        print("************************");
        //得到指定路径的文件  名
        string[] str2= Directory.GetFiles(Application.dataPath);
        for (int i = 0; i < str2.Length; i++)
        {
            //print(str2[i]);
        }
        //移动文件夹
        //确保第二个文件没有被创建 不然会报错    
        //内容也会跟着走 
       // Directory.Move(Application.dataPath + "/二进制操作" , Application.dataPath + "/123123");

        print("************************");
        //文件夹目录信息
        DirectoryInfo directoryInfo= Directory.CreateDirectory(Application.dataPath + "/ccc");
        //文件所在路径
        print(directoryInfo.FullName);
        print(directoryInfo.Name);
      

        directoryInfo= Directory.GetParent(Application.dataPath + "/ccc");
        print(directoryInfo.FullName);
        print(directoryInfo.Name);
        print("************************");
        //子文件夹信息
      DirectoryInfo[] directoryInfo1=  directoryInfo.GetDirectories();

        print("************************");
        FileInfo[] fileInfo = directoryInfo.GetFiles();
        for (int i = 0; i < fileInfo.Length; i++)
        {
            print(fileInfo[i].FullName);
            print(fileInfo[i].Name);
          
            print(fileInfo[i].Length);
            print(fileInfo[i].Extension);//后缀名
        }

3.对一个类的序列化和反序列化 

 public class person{
        public int age;
        public string name;
        public bool isactive;
       public  person()
        {
            this.age = 18;
            this.name = "ccc";
            this.isactive = true;
        }
        public  byte[] GetBytes()
        {
            //声明字符数组的长度
            int cavatity = sizeof(int) + Encoding.UTF8.GetBytes(name).Length + sizeof(bool)+100;
            //声明一个字符数组容器
            byte[] byteres = new byte[cavatity];
            //
            int index = 0;

            //int
            byte[] byte1 = BitConverter.GetBytes(age);
            byte1.CopyTo(byteres, index);
            index += sizeof(int);

            //存长度
            byte[] strByte = Encoding.UTF8.GetBytes(name);
            int sInt = strByte.Length;
            BitConverter.GetBytes(sInt).CopyTo(byteres, index);
            index += sizeof(int);
            //存字符串
            strByte.CopyTo(byteres, index);
            index += sInt;

            //bool
            byte[] byte2 = BitConverter.GetBytes(isactive);
            byte2.CopyTo(byteres, index);
            index += sizeof(bool);

            return byteres;
        }
    }

3.序列化为二进制 和反序列化二进制

序列化:

  //二进制操作
        Person p=new Person();
        //方法一 写入到内存流当中 一般用于网络传输
        using(MemoryStream ms=new MemoryStream())
        {
            BinaryFormatter bf=new BinaryFormatter();
            //序列化对象 生成p的字节数组 写入到内存流里面
            bf.Serialize(ms, p);
            //得到字节数组
            byte[]bytes=ms.GetBuffer();
            //存储字节
            File.WriteAllBytes(Application.dataPath + "/序列化为二进制",bytes);
            //关闭文件流
            ms.Close();
        }
        //方法二 直接写入到文件流
        using (FileStream fileStream = new FileStream(Application.dataPath + "/序列化为二进制2", FileMode.OpenOrCreate, FileAccess.ReadWrite))
        {
           BinaryFormatter bf2= new BinaryFormatter();
            //这句代码会把p直接转换成字节形式写入到fileStream中
            bf2.Serialize(fileStream, p);
            fileStream.Flush();
            fileStream.Close();
        }
    }

反序列化:

  //反序列化
        //直接从文件读
        //Deserialize
        using (FileStream fs = new FileStream(Application.dataPath + "/序列化为二进制", FileMode.OpenOrCreate, FileAccess.ReadWrite))
        {
            BinaryFormatter bf3= new BinaryFormatter();
            Person p1=  bf3.Deserialize(fs) as Person;
            fs.Close();
        }
        //文件流
        //需要先得到字节数组 用来初始化内存流对象
        byte[] bytes1 = File.ReadAllBytes((Application.dataPath + "/序列化为二进制2"));
        using(MemoryStream ms=new MemoryStream(bytes1))
        {
            BinaryFormatter bf4= new BinaryFormatter();
            Person p2=  bf4.Deserialize(ms) as Person;
            ms.Close();
        }
    }

实践:

1.Unity添加菜单按钮

MenuItem特性

   //代码文件要放到Enditor文件夹下面 因为打包之后不需要访问编辑器代码文件了
    //加MenuItem特性  必须至少有两个目录
    [MenuItem("GameTool/Test")]
    //方法必须是静态的
   public static void Test()
    {
        print("测试");
        //代码直接写 刷新Progrect界面
        AssetDatabase.Refresh();
    }

2. 补充 打开并读取Excel表的具体信息

//根据文件流读取Excel表

 IExcelDataReader excelReader= ExcelReaderFactory.CreateOpenXmlReader(fs);

//几个类

 DataSet、DataTable 、DataRow

 [MenuItem("GameTool/打开Excel集")]
    public static  void OpenExcel()
    {
        using (FileStream fs = File.Open(Application.dataPath + "/ArtRes/Excel/playerInfo.xlsx",FileMode.Open,FileAccess.Read))
        {
            //通过fs读取Excel数据
            IExcelDataReader excelReader= ExcelReaderFactory.CreateOpenXmlReader(fs);
            //转换成DataSet方便读取
            DataSet result=excelReader.AsDataSet();
            for (int i = 0; i < result.Tables.Count; i++)
            {
                Debug.Log(result.Tables[i].TableName);
                Debug.Log(result.Tables[i].Rows.Count);
                Debug.Log(result.Tables[i].Columns.Count);
            }
            fs.Close();
        }
    }
    [MenuItem("GameTool/读取Excel表的具体信息")]
    public static void ReadExcel()
    {
        using (FileStream fs = File.Open(Application.dataPath + "/ArtRes/Excel/playerInfo.xlsx", FileMode.Open, FileAccess.Read))
        {
            IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(fs);
            DataSet result = excelReader.AsDataSet();
            for (int i = 0; i < result.Tables.Count; i++)
            {
                //某一张表的数据 DataTable
                DataTable table = result.Tables[i];
                //某一张表的数据 DataRow
                DataRow row;
                for (int j = 0; j < table.Rows.Count; j++)
                {
                    row = table.Rows[j];
                    Debug.Log("新的一行********");
                    //每一列的信息
                    for (int k = 0; k < table.Columns.Count; k++)   
                    {
                        Debug.Log(row[k].ToString());
                        //生成数据结构文件
                        GeneratorClass(table);
                        //生成容器类
                        GeneratorConstainer( table);
                        GenerateExcelBinary(table);
                    }
                }
            }
        }
    }

3.生成数据结构类

 public  static void GeneratorClass(DataTable table)
    {
        //生成数据结构文件
        //得到表中变量名字的那一行
        DataRow rowname = GetVaribleNameRow(table);
        //得到表中变量类型的那一行
        DataRow typename = GetVaribleTypeRow(table);
        //存储数据文件类的路径
        if (!Directory.Exists(ClASS_PATH))
        {
            Directory.CreateDirectory(ClASS_PATH);
        }
        //一系列拼接
        string str = "public class " + table.TableName+"{\n";
        for (int i = 0; i < table.Columns.Count; i++)
        {
            str += "  public " + typename[i].ToString() + " " + rowname[i].ToString() + ";\n";
        }
        str += "}";
        //最后通过File写入 
        File.WriteAllText(ClASS_PATH+table.TableName + ".cs", str);
        //刷新
        AssetDatabase.Refresh();
    }

调用后

5.创建容器类

    public static void GeneratorConstainer(DataTable table)
    {
        //设置通过Excel配置的主键为字典的主键
        int key = GetKey(table);
        //自定义规则 Excel表名和类名相同
        //得到这个表的类型 就是创建的数据结构类  
        DataRow rowtype = GetVaribleTypeRow(table);
        if(!Directory.Exists(CONSTAINER_PATH))
        {
            Directory.CreateDirectory (CONSTAINER_PATH);
        }
        string str = "using System.Collections.Generic;\n";
        str += "public class  " + table.TableName + "Constainer"+"\n{\n";
        str += " ";
        str += "public Dictionary< "+rowtype[key].ToString()+","+table.TableName+">";
        str += "dataDic = new  "+"Dictionary<"+rowtype[key].ToString()+","+table.TableName+">();\n";
        str += "}";
        File.WriteAllText(CONSTAINER_PATH + table.TableName + "Constainer.cs" , str);
        AssetDatabase .Refresh();
    }

调用后

6.生成二进制数据

 public static void GenerateExcelBinary(DataTable table)
    {
        if(!Directory.Exists (BINARY_PATH))
        {
            Directory.CreateDirectory (BINARY_PATH);
        }
        using (FileStream fs = new FileStream(BINARY_PATH + table.TableName + ".ccc", FileMode.OpenOrCreate, FileAccess.ReadWrite))
        {
            //存储 一共有多少行
            fs.Write(BitConverter.GetBytes(table.Rows.Count-4),0, 4);
            //存储主键的变量名
            //后面是通过字典来 . 点出数据 
            string keyname=GetVaribleNameRow(table)[GetKey(table)].ToString();
            byte[]bytes=Encoding.UTF8.GetBytes(keyname);
            //存储的字符串字节长度
            fs.Write(BitConverter.GetBytes(bytes.Length), 0, 4);
            //存储字符串字节数组
            fs.Write(bytes, 0, bytes.Length);

            DataRow row;
            DataRow rowtype = GetVaribleTypeRow(table);

            for (int i = 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;
                        default:
                            break;
                    }
                }
            }
            fs.Close();
            AssetDatabase.Refresh();
        }
    }

乱码了... 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值