如何压缩4字节的长度,以适应1字节的标签长度-值流?



我看到这个家伙为Tag-Length-Value做了一些不同的事情,他允许存储大长度>正如我们在TLV示例中看到的,它是这样工作的:

我需要存储我的ID + Name

标签1,长度5,值(ID) = 12345,等等

回到我需要的,这个家伙/TlvEncoding如何压缩长度以允许存储超过4个字节。例如:

假设我有一个长度为1000的字符串,超过1字节。

备注:0xffff = 65,535UInt16ushort的最大值。我想这条线上长度达到1000的条件。流将写入2字节的长度。但当他读到这个值时,他会做更多的逻辑操作。我已经泄露了。(

/// <summary>
/// Write TLV length to stream
/// </summary>
/// <param name="stream">stream to write to</param>
/// <param name="length">length to write or null to write indefinite length</param>
public static void WriteLength(Stream stream, int? length)
{
if (length == null)
{
stream.WriteByte(0x80); // indefinite form
return;
}
if (length < 0 || length > 0xffffffff)
throw new TlvException(string.Format("Invalid length value: {0}", length));
if (length <= 0x7f) // use short form if possible
{
stream.WriteByte(checked((byte)length));
return;
}
byte lengthBytes;
// use minimum number of octets
if (length <= 0xff)
lengthBytes = 1;
else if (length <= 0xffff)
lengthBytes = 2;
else if (length <= 0xffffff)
lengthBytes = 3;
else if (length <= 0xffffffff)
lengthBytes = 4;
else
throw new TlvException(string.Format("Length value too big: {0}", length));
stream.WriteByte((byte)(lengthBytes | 0x80));
// shift out the bytes
for (var i = lengthBytes - 1; i >= 0; i--)
{
var data = (byte)(length >> (8 * i));
stream.WriteByte(data);
}
}

在读取操作他做:(我认为条件将满足这里0x7f; // remove 0x80 bit)我不知道他为什么选择等于127的0x7f,而去掉等于128的0x80。

/// <summary>
/// Read TLV length from stream
/// </summary>
/// <param name="stream">Stream to read</param>
/// <returns>length or null to indicate indefinite length</returns>
public static int? ReadLength(Stream stream)
{
var readByte = stream.ReadByte();
if (readByte == -1)
throw new TlvException("Unexpected end of stream while reading length");
if ((readByte & 0x80) == 0)
return (int)readByte; // length is in first byte
int length = 0;
var lengthBytes = readByte & 0x7f; // remove 0x80 bit
if (lengthBytes == 0)
return null; // indefinite form
if (lengthBytes > 4)
throw new TlvException($"Unsupported length: {lengthBytes} bytes");
for (var i = 0; i < lengthBytes; i++)
{
readByte = stream.ReadByte();
if (readByte == -1)
throw new TlvException("Unexpected end of stream while reading length");
length <<= 8;
length |= (int)readByte;
}
return length;
}

请我只需要了解事情是如何发生的,因为我需要在字节数组中应用相同的方法。我需要存储即:1500长度的字符串,日期时间,一些整数,作为(tlv)。但是我只知道如何应用1字节长度(255)。

所以我只能读取1字节的长度,因为我不知道如何告诉数组我需要寻找3字节的长度?还是2个字节?然后我必须用2或3字节存储所有tlv。那是浪费空间。

  1. 整数存储为4字节(OK),所以我可以写长度是(byte) 4(注意字节转换)
  2. 字符串只能存储在255中但是怎么像上面那个人那样做呢?1500长度在3字节?

我简单地解释一下,他允许存储1字节作为长度,有时存储3字节作为长度。我甚至不知道他如何告诉编译器/流从接下来的3个字节读取这个标签长度。或者接下来的2个字节。或1个字节

WriteLength来看,它看起来相当简单。

0到0x7F之间的值仅用该值的单个字节表示。例如,如果你想写入值5,你写一个值5的字节。

For values>0 x7f:

  1. 第一个字节是表示值所需的字节数,设置最高位(以便您可以区分它与保存0-127之间值的简单字节之间的区别)
  2. 下一个字节保留实际值。
<表类> 价值 序列化 tbody><<tr>00 x0010 x011270 x7f1280 x81 0 x801290 x81 0 x812550 x81 0 xff2560x82 0x01 0x002570x82 0x01 0x01655350x82 0xFF 0xFF655360x83 0x01 0x00 0x00 0x00

最新更新