C# 中的字符串长度前缀采用了变长字节数组表示。
using System;
using System.Text;
using System.IO;
namespace ConsoleApp14
{
internal class Program
{
static void Main(string[] args)
{
string s = "abcd";
byte[] bytes = Encoding.UTF8.GetBytes(s);
//将字符串写入内存流
var ms = new MemoryStream();
Write7BitEncodedInt(bytes.Length, ms);
ms.Write(bytes, 0, bytes.Length);
ms.Position = 0;
//从内存流中读取字符串
var reader = new BinaryReader(ms);
Console.WriteLine(reader.ReadString());
Console.ReadKey();
}
/// <summary>
/// 写入字符串长度前缀到内存流,这个长度前缀所占字节数是动态的。
/// 每个字节的第8bit表示后面是否还跟有长度前缀字节,只有字节中的右边7bit用来表示大小。
/// 例如,一个长度为128的字符串,它的长度前缀为 [10000000, 00000001],
/// 需要注意的是长度前缀用的是小端表示,所以数组中第2个字节代表 00000001=1x128
/// </summary>
/// <param name="value"></param>
/// <param name="ms"></param>
public static void Write7BitEncodedInt(int value, MemoryStream ms)
{
uint num;
for (num = (uint)value; num >= 128; num >>= 7)
{
//以小端顺序写入到流中
//每次存储7bit到写入的字节中,并在第8bit上做上标记
ms.WriteByte((byte)(num | 0x80u));
}
ms.WriteByte((byte)num);
}
/// <summary>
/// 从内存流中读取字符串长度前缀
/// </summary>
/// <param name="ms"></param>
/// <returns></returns>
/// <exception cref="FormatException"></exception>
public static int Read7BitEncodedInt(MemoryStream ms)
{
int num = 0;
int num2 = 0;
byte b;
do
{
if (num2 == 35)
{
throw new FormatException("Format_Bad7BitInt32");
}
b = (byte)ms.ReadByte();
//提取出7bit有效位放入num中
num |= (b & 0x7F) << num2;
num2 += 7;
}
while ((b & 0x80u) != 0);
return num;
}
}
}