C#存儲和讀取自定義結構到二進制文件。以及byte數據壓縮,4bit拆分做法。

使用二進制文件存儲,可以在不壓縮數據的前提下儘量的節省空間。

情景:在使用Unity製作遊戲的時候,需要存儲一個非常大的信息。大概是千萬級別(8192×8192)的byte數組。然後計算內存大概是8192*8192/1024/1024 = 64 MB大小

使用Json存儲

後來我用json存下了文件,到處之後。發現內存600MB,這樣遊戲裏肯定是沒有辦法用的。於是看了.json文件。到處之後多了很多逗號、空格,所以佔用了很多的內存空間。於是使用:
public static string ToJson(object obj, bool prettyPrint); 去掉了所有的空格,這樣導出之後的內存是128MB,畢竟json的 逗號 是去不掉的。。至此放棄Json文件保存信息。

使用二進制保存

放棄Json之後,想了想目測二進制可以沒有 逗號 直接存儲爲文件。這樣的話起碼可以把內存控制在64MB。結果還可以接受。於是開始設想怎麼自定義一個方法存儲我的結構(Struct),要不要自定義存儲和讀取方式之類。想了想沒什麼頭緒,於是面向Google編程試試,發現自定義的結構可以直接格式化輸出到硬盤。代碼如下:

//引用庫
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

//示例方法
void Save (string customPath)
    {
        FileStream fs = new FileStream(customPath,FileMode.Create);
        BinaryFormatter bFormatter = new BinaryFormatter();
        bFormatter.Serialize(fs, customPath);
        fs.Flush();
        fs.Close();
	}

這樣就可以直接將自定義結構存儲爲二進制文件了,讀取的時候也很方便,使用下列代碼即可。

void Load (string customPath)
    {
        FileStream fs = new FileStream(customPath,FileMode.Open);
        BinaryFormatter bFormatter = new BinaryFormatter();
        bFormatter.Deserialize(fs);
        fs.Close();
	}

這樣就可以實現存儲和讀取二進制文件的功能了。

二進制保存+數據壓縮

OK上邊說到了直接使用C#的BinaryFormatter()方法進行序列化。但是內存只是達到了一開始的預計內存64MB。那麼還有沒有辦法能再節省一些內存呢。於是我研究了我要存儲的數據,發現數據大小隻有從0-4幾個範圍,其實只需要3個bit就可以存下來。完全可以把1個byte的8bit拆分爲兩個存儲數據。
在這裏插入圖片描述
下面寫具體的做法:
我們採用4bit存一個數據的話,可以先把要存的第一個數據存到一個byte裏然後做左移運算,存到高位。要存的第二個數據不用動。然後通過兩個byte 或 運算,獲得要存儲的byte數據。之後取的話,取高位數據時右移,取低位數據時和0000 1111(10進制下15)做與運算,即可取到低位數據。
過程如下圖:
在這裏插入圖片描述
C#實現:

//取
public static byte UnpackByte(byte oriByte,bool isLow)
    {
        if (isLow)
        {
            return (byte)(oriByte & 15);
        }
        else
        {
            return (byte)(oriByte>> 4);
        }
    }
//存
    public static byte SaveByte(byte data,bool isLow)
    {
        if (isLow)
        {
            return (byte)((data & 15)<<4);
        }
             
        else
        {
            //低位
            byte fbit1 = (byte)(data & 15);
            byte fbit2 = (byte)(data & 240);

            return (byte)(fbit2 | fbit1);
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章