Binário de persistência de dados do Unity (parte 2)

Mencionamos no último artigo que usar código para manipular arquivos em C#, vamos ver como usar código para manipular pastas em C# a seguir. C# fornece uma classe pública de operação de pasta Directory , que nos fornece alguns métodos para operar pastas.

Métodos no diretório

1. Determine se a pasta existe

2. Crie uma pasta

O código é o seguinte, se houver uma pasta, imprima "pasta existe", caso contrário, imprima "pasta não existe" e crie uma pasta

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

3. Exclua a pasta

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

4. Encontre a pasta especificada e o arquivo especificado

        //得到指定路径下的所有文件夹名
        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. Mova a pasta (o primeiro parâmetro é o caminho do arquivo original e o segundo parâmetro é o caminho do arquivo de destino)

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

Os métodos acima são os métodos comumente usados ​​fornecidos no Directory. Com base nisso, também podemos obter mais informações sobre as pastas por meio do DirectoryInfo

Classe de informações do diretório DirectoryInfo e classe de informações do arquivo FileInfo

        //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() 
        }

Depois de entender a conversão de bytecode mencionada acima, a operação da pasta de arquivos e o uso relacionado de fluxos de dados, podemos tentar desserializar objetos . Vamos declarar alguns exemplos de tipos de dados que precisam ser serializados.

Serialização de objetos de classe

Dois tipos de classe (uma Person, uma ClassTesr) e um tipo de estrutura (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;
    }

 Existem duas maneiras de desserializar uma instância da classe Person, armazenamento de fluxo de arquivo e armazenamento de fluxo de memória:

Método 1: Use um fluxo de memória para obter uma matriz de bytes binários

        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();
            //关闭内存流下
        }

Sua essência é converter o objeto em formato binário por meio de BinaryFormatter, gravá-lo no fluxo de memória e, em seguida, obter a matriz de palavras binárias do fluxo de memória e, finalmente, gravá-lo no arquivo por meio de File. Feche o fluxo de memória.

Método 2: Use fluxos de arquivos para armazenamento

            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();
        }

A essência desse método também precisa usar BinaryFormatter para converter o binário, gravar o arquivo diretamente por meio do fluxo de arquivo FileStream e, finalmente, fechar o fluxo de arquivo.

Depois, há a desserialização. A essência da desserialização é a mesma da serialização. Eles basicamente usam a classe BinaryFormatter e a classe FileStream (porque o desenvolvimento da rede Unity ainda não foi tocado), então o fluxo de memória MemoryStream ainda é usado para ler dados.

Desserialização de objetos de classe:

        #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
    }

Sua essência é declarar um fluxo de objeto ou fluxo de arquivo, passar o arquivo que precisa ser sequenciado e desserializado para o objeto BinaryForamatter e, em seguida, converter o valor de retorno para o mesmo tipo.

Depois de aprender as operações básicas de serialização e desserialização de objeto, você pode tentar escrever uma classe singleton para esta operação, o código é o seguinte

Serializar uma única classe de coluna

    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;
    }
}

Acho que você gosta

Origin blog.csdn.net/qq_52690206/article/details/127791518
Recomendado
Clasificación