Unity データ永続化バイナリ (パート 2)

前回の記事では、コードを使用して C# でファイルを操作することについて説明しました。次に、コードを使用して C# でフォルダーを操作する方法を見てみましょう。C# にはフォルダー操作のパブリック クラス Directory が用意されており、フォルダーを操作するためのメソッドがいくつか提供されます。

ディレクトリ内のメソッド

1. フォルダーが存在するかどうかを確認します

2. フォルダーを作成する

コードは次のとおりです。フォルダーが存在する場合は「フォルダーが存在します」を出力し、存在しない場合は「フォルダーが存在しません」を出力してフォルダーを作成します。

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

3. フォルダーを削除します

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

4. 指定したフォルダーと指定したファイルを検索します

        //得到指定路径下的所有文件夹名
        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. フォルダーを移動します (最初のパラメーターは元のファイル パス、2 番目のパラメーターはターゲット ファイル パスです)

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

上記は Directory で提供される一般的に使用されるメソッドです。これに基づいて、DirectoryInfo を通じてフォルダーに関する詳細情報を取得することもできます。

DirectoryInfo ディレクトリ情報クラスと 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() 
        }

前述のバイトコード変換、ファイル フォルダーの操作、および関連するデータ ストリームの使用法を理解した後、オブジェクトの逆シリアル化を試みることができます。シリアル化する必要があるデータ型の例をいくつか宣言してみましょう。

クラスオブジェクトのシリアル化

2 つのクラスタイプ (1 つは Person、1 つの ClassTesr) と 1 つの構造タイプ (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;
    }

 Person クラス インスタンスを逆シリアル化するには、ファイル ストリーム ストレージとメモリ ストリーム ストレージの 2 つの方法があります。

方法 1: メモリ ストリームを使用してバイナリ バイト配列を取得する

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

その本質は、BinaryFormatter を通じてオブジェクトをバイナリ形式に変換し、それをメモリ ストリームに書き込み、次にメモリ ストリームからバイナリ ワード配列を取得し、最後にそれを File を通じてファイルに書き込むことです。メモリ ストリームを閉じます。

方法 2: ストレージにファイル ストリームを使用する

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

このメソッドの本質では、BinaryFormatter を使用してバイナリを変換し、FileStream ファイル ストリームを通じてファイルを直接書き込み、最後にファイル ストリームを閉じる必要もあります。

次に、逆シリアル化があります逆シリアル化の本質はシリアル化と同じです。基本的には BinaryFormatter クラスと FileStream クラスを使用します (Unity ネットワーク開発にはまだ触れていないため)。そのため、データの読み取りには依然として MemoryStream メモリ ストリームが使用されます。

クラスオブジェクトの逆シリアル化:

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

その本質は、オブジェクト ストリームまたはファイル ストリームを宣言し、シーケンス化して逆シリアル化する必要があるファイルを BinaryForamatter オブジェクトに渡し、戻り値を同じ型に変換することです。

オブジェクトのシリアル化と逆シリアル化の基本操作を学習した後、この操作用のシングルトン クラスを作成してみることができます。コードは次のとおりです。

単一列クラスをシリアル化する

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

おすすめ

転載: blog.csdn.net/qq_52690206/article/details/127791518
おすすめ