Unity Data Persistence Binary (Part 2)

We mentioned in the last article that using code to manipulate files in C#, let's see how to use code to manipulate folders in C# next. C# provides a folder operation public class Directory , which provides us with some methods for operating folders.

Methods in Directory

1. Determine whether the folder exists

2. Create a folder

The code is as follows, if there is a folder, print "folder exists", otherwise print "folder does not exist" and create a folder

        if (Directory.Exists(Application.dataPath + "/DataPersistance"))
        {
            print("存在文件夹");
        }
        else
        {
            print("文件夹不存在");
            //2.创建文件夹
            DirectoryInfo info = Directory.CreateDirectory(Application.dataPath + "/DataPersistance");
        }

3. Delete the folder

        //3.删除文件夹   
        //参数一:路径
        //参数二:是否删除非空目录,如果为true,将删除整个目录,如果是false,仅当改目录为空时才可以删除
        /Directory.Delete(Application.dataPath + "/DataPersistance");

4. Find the specified folder and specified file

        //得到指定路径下的所有文件夹名
        string[] strs = Directory.GetDirectories(Application.dataPath);
        for (int i = 0; i < strs.Length; i++)
        {
            print(strs[i]);   
        }

        //得到指定路径下的所有文件名
        strs = Directory.GetFiles(Application.dataPath);
        for (int i = 0; i < strs.Length; i++)
        {
            print(strs[i]);
        }

 5. Move the folder (the first parameter is the original file path, and the second parameter is the target file path)

        //5.移动文件夹
        //如果第二个参数所在的路径已经存在了一个文件夹 就会报错
        //移动会把文件夹中的所有内容 一起移动到新的路径
        Directory.Move(Application.dataPath + "/DataPersistance", Application.dataPath+"/moveFile");

The above are the commonly used methods provided in Directory. On this basis, we can also obtain more information about folders through DirectoryInfo

DirectoryInfo directory information class and FileInfo file information class

        //DirectoryInfo目录信息类
        //我们可以通过它获取文件夹的更多信息
        //它主要出现在两个地方
        //1.创建文件夹方法的返回值
        DirectoryInfo dInfo = Directory.CreateDirectory(Application.dataPath + "/DataPersistance2");
        print("**********************");
        //全路径
        print(dInfo.FullName);
        //文件名
        print(dInfo.Name);

        //2.查找上级文件夹信息
        dInfo = Directory.GetParent(Application.dataPath + "/DataPersistance2");
        print("**********************");
        //全路径
        print(dInfo.FullName);
        //文件名
        print(dInfo.Name);

        //重要方法 
        //得到所有文件夹的目录信息
        FileInfo[] fInfos = dInfo.GetFiles();
        for (int i = 0; i <fInfos.Length; i++)
        {
            print(fInfos[i].Name);//文件名
            print(fInfos[i].FullName);//路径
            print(fInfos[i].Length);//字节长度
            print(fInfos[i].Extension);//后缀名

            //返回一个文件流
            //fInfos[i].Open() 
        }

After understanding the above-mentioned bytecode conversion, file folder operation, and related use of data streams, we can try to deserialize objects . Let's declare some examples of data types that need to be serialized.

Serialization of class objects

Two class types (one Person, one ClassTesr) and one structure type (StructTest)

        [System.Serializable]
    public class Person
    {
        public int age = 1;
        public string name = "mqx";
        public int[] ints = new int[] { 1, 2, 3, 4, 5 };
        public List<int> list = new List<int>() { 1, 2, 3, 4, 5 };
        public Dictionary<int, string> dic = new Dictionary<int, string>() { { 1, "NO.1" }, { 2, "NO.2" }, { 3, "NO.3" } };
        public StructTest st = new StructTest(2, "123");
        public ClassTest ct = new ClassTest();
    }
    [System.Serializable]
    public struct StructTest {
        public int i;
        public string s;
        public StructTest(int i,string s)
        {
            this.i = i;
            this.s = s;
        }
    }
    [System.Serializable]
    public class ClassTest {
        public int i = 1;
    }

 There are two ways to deserialize a Person class instance, file stream storage and memory stream storage:

Method 1: Use a memory stream to get a binary byte array

        using (MemoryStream ms = new MemoryStream())
        {
            //二进制格式化程序
            BinaryFormatter bf = new BinaryFormatter();
            //生产二进制字节数组 写入到内存流中
            bf.Serialize(ms, person);
            //得到对象的二进制字节数组
            byte[] bytes = ms.GetBuffer();
            //存储字节
            File.WriteAllBytes(Application.dataPath + "/Lesson5.mqx", bytes);
            ms.Close();
            //关闭内存流下
        }

Its essence is to convert the object into binary format through BinaryFormatter, write it into the memory stream, and then obtain the binary word array from the memory stream, and finally write it into the file through File. Close the memory stream.

Method 2: Use file streams for storage

            using (FileStream fs = new FileStream(Application.dataPath+"/Lesson5_2",FileMode.OpenOrCreate,FileAccess.Write)) { 
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(fs, person);
            fs.Flush();
            fs.Close();
        }

The essence of this method also needs to use BinaryFormatter to convert the binary, then write the file directly through the FileStream file stream, and finally close the file stream.

Then there is deserialization. The essence of deserialization is the same as serialization. They basically use the BinaryFormatter class and the FileStream class (because Unity network development has not been touched yet), so the MemoryStream memory stream is still used to read data.

Deserialization of class objects:

        #region 反序列化之 反序列化文件中的数据
        //主要类
        //FileStream文件流
        //BinaryFormatter
        //主要方法
        //Deserizlize
        using (FileStream fs = File.Open(Application.dataPath + "/Lesson5_2", FileMode.Open, FileAccess.ReadWrite)) {
            BinaryFormatter bf = new BinaryFormatter();
            Lesson5.Person p= bf.Deserialize(fs) as Lesson5.Person;
        }
        #endregion

        #region 反序列之反序列化网络传输过来二进制数据
        //主要类 
        //MemoryStream内存流类
        //BinaryFormatter 二进制格式化类
        //主要方法
        //Deserizlize
        //目前没有网络传输就直接从文件获取
        byte[] bytes = File.ReadAllBytes(Application.dataPath + "/Lesson5_2.mqx");

        //声明内存流对象 一开始就把字节流数组传输进去
        using (MemoryStream ms=new MemoryStream (bytes)) {
            BinaryFormatter bf = new BinaryFormatter();
            Lesson5.Person p= bf.Deserialize(ms) as Lesson5.Person;
            ms.Close();
        }
        #endregion
    }

Its essence is to declare an object stream or file stream, pass the file that needs to be sequenced and deserialized into the BinaryForamatter object, and then convert the return value as to the same type.

After learning the basic operations of object serialization and deserialization, you can try to write a singleton class for this operation, the code is as follows

Serialize a single column class

    public class BinaryDataMgr
{
    private static BinaryDataMgr instance = new BinaryDataMgr();
    public static BinaryDataMgr Instance => instance;
    private BinaryDataMgr() { }

    private static string SAVE_PATH = Application.persistentDataPath + "/Data/";

    /// <summary>
    /// 存储类对象数据
    /// </summary>
    /// <param name="data">需要存储的对象</param>
    /// <param name="fileName">文件名</param>
    public void Save(object data,string fileName) {
        //判断路径文件夹是否存在
        if (Directory.Exists(SAVE_PATH))
        {
            Directory.CreateDirectory(SAVE_PATH);
        }
        using (FileStream fs = new FileStream(SAVE_PATH+fileName+".mqx",FileMode.OpenOrCreate,FileAccess.Write)) {
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(fs, data);
            fs.Close();
        }
    }

    /// <summary>
    /// 读取二进制数据转换为类对象
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="fileName">文件名</param>
    /// <returns></returns>
    public T Load<T>(string fileName) where T:class {
        if (!File.Exists(SAVE_PATH+fileName+".mqx"))
        {
            return default(T);
        }
        T obj;
        using (FileStream fs=File.Open(SAVE_PATH+fileName +".mqx",FileMode.Open,FileAccess.Read)) {
            BinaryFormatter bf = new BinaryFormatter();
            obj = bf.Deserialize(fs) as T;
            fs.Close();
        }
        return obj;
    }
}

Guess you like

Origin blog.csdn.net/qq_52690206/article/details/127791518