使用二進制文件存儲,可以在不壓縮數據的前提下儘量的節省空間。
情景:在使用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);
}
}