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拆分为两个存储数据。
C#存储和读取自定义结构到二进制文件。以及byte数据压缩,4bit拆分做法。_第1张图片
下面写具体的做法:
我们采用4bit存一个数据的话,可以先把要存的第一个数据存到一个byte里然后做左移运算,存到高位。要存的第二个数据不用动。然后通过两个byte 或 运算,获得要存储的byte数据。之后取的话,取高位数据时右移,取低位数据时和0000 1111(10进制下15)做与运算,即可取到低位数据。
过程如下图:
C#存储和读取自定义结构到二进制文件。以及byte数据压缩,4bit拆分做法。_第2张图片
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);
        }
    }

你可能感兴趣的:(C#)