一种基于偏移流和纯字符串流来存储和读取字符串列表的方法【C#】

字符串的存储长度是可变的,在C#中,BinaryWriter和BinaryReader在Write,ReadStirng的时候,都在单个流中字符串的二进制数组前面加了一个二进制数组的长度信息,方便读取的时候,造成了记录字符串的流并不纯粹是字符串的内容。但是,有时候,我们可以,也可能必须记录纯粹的字符串的二进制内容,然后辅以另一个偏移流,来实现字符串列表的存储与读写(比如:https://github.com/CesiumGS/3d-tiles/tree/main/specification/Metadata#binary-table-format)

针对这种情况的demo如下:
write:


var strs = new List<string> { "EBPlate", "EBBeam", "EBWall", "EBColumn" };
FileStream fs1 = new FileStream("content.bin", FileMode.Create), fs2 = new FileStream("offset.bin", FileMode.Create);
BinaryWriter bs2 = new BinaryWriter(fs2);
int offset = 0;
foreach(var  str in strs)
{
    bs2.Write(offset);
    byte[] bytes=UTF8Encoding.UTF8.GetBytes(str);
    fs1.Write(bytes, 0, bytes.Length);  
    offset += bytes.Length;
}
bs2.Write(offset);
fs1.Close();fs2.Close();
bs2.Close();

read


FileStream fs1 = new FileStream("content.bin", FileMode.Open), fs2 = new FileStream("offset.bin", FileMode.Open);
BinaryReader br1 = new BinaryReader(fs1), br2 = new BinaryReader(fs2);
long count = fs2.Length / sizeof(int);
var offsets = new List<int>();
var strs = new List<string>();
for(int i = 0; i < count; i++)
{
    int ivalue = br2.ReadInt32();
    offsets.Add(ivalue);
}
for(int i=0;i<offsets.Count-1;i++ )
{
    int start = offsets[i];
    int length = offsets[i + 1]-start;
    byte[] b=new byte[length];
    fs1.Read(b,0,length);
    var str=Encoding.UTF8.GetString(b);
    strs.Add(str);
}
foreach(var str in strs)
{
    Console.WriteLine(str);
}
fs1.close();fs2.close();br1.close();

posted @ 2024-01-15 10:14  JohnYang819  阅读(7)  评论(0编辑  收藏  举报