这里就不介绍Varint编码的原理了,请自行查找原理并理解,这里只是在C#上对Varint编码、解码的实现。
using System;
/// <summary>
/// varint编码
/// </summary>
public class VarintUtil
{
/// <summary>
/// 把value采用varint编码写入outBuffer
/// </summary>
/// <param name="outBuffer"></param>
/// <param name="value"></param>
public static byte[] WriteRawVarint32(int value, int length)
{
// 数据长度
byte[] varIntBuffer = new byte[length];
int index = 0;
while (true)
{
if ((value & ~0x7f) == 0)
{
varIntBuffer[index] = (byte)(value & 0x7f);
break;
} else
{
varIntBuffer[index] = (byte)((value & 0x7f) | 0x80);
value = value >> 7;
}
index++;
}
return varIntBuffer;
}
/// <summary>
/// 计算value实际长度
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static int ComputeRawVarint32Size(Int32 value)
{
if ((value & (0xffffffff << 7)) == 0)
{
return 1;
}
if ((value & (0xffffffff << 14)) == 0)
{
return 2;
}
if ((value & (0xffffffff << 21)) == 0)
{
return 3;
}
if ((value & (0xffffffff << 28)) == 0)
{
return 4;
}
return 5;
}
/// <summary>
/// 某个byte是否是varint编码的结束字节
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static bool IsVarintEnd(byte value)
{
return (value & 0x80) == 0;
}
/// <summary>
/// 将byte[]转化为对应的int
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
public static int GetVarintValue(byte[] buffer)
{
Int32 result = 0;
for(int i = 0; i < buffer.Length; i++)
{
byte value = buffer[i];
if ((value & 0xff) == 0)
{
break;
}
result = result | (value & 127) << (7 * i);
}
return result;
}
}
调用方式:
private void VarintTests()
{
VarintTest(12);
VarintTest(128);
VarintTest(100028);
VarintTest(2361028);
VarintTest(659851028);
VarintTest(1023654528);
}
private void VarintTest(Int32 value)
{
int varLength = VarintUtil.ComputeRawVarint32Size(value);
LogUtil.Log(this, "value length: ", varLength, ",value:", value);
byte[] lengthBuffer = VarintUtil.WriteRawVarint32(value, varLength);
string str = "";
for(int i = 0; i < lengthBuffer.Length; i++)
{
str += lengthBuffer[i] + " ";
}
byte[] lengthBuffer2 = new byte[5];
int index = 0;
while (true)
{
byte bbb = lengthBuffer[index];
lengthBuffer2[index] = bbb;
index++;
if (VarintUtil.IsVarintEnd(bbb))
{
break;
}
}
Int32 length = VarintUtil.GetVarintValue(lengthBuffer2);
LogUtil.Log(this, "receive length:", length);
}
运行结果:(这里基本测试了Int32能表达的所有数了结果如下)