提问人:Momo 提问时间:5/22/2022 更新时间:5/22/2022 访问量:458
如何压缩 4 字节的长度以仅适合 1 字节的 Tag-Length-Value 流?
How to compress Length of 4 Bytes to fit into 1 Byte only of Tag-Length-Value stream?
问:
我看到这个家伙对 Tag-Length-Value 做了一些不同的事情,他允许存储 255 >的大长度,正如我们在 TLV 示例中看到的那样,它的工作原理是这样的:
我需要存储我的 ID + 姓名
标记 1、长度 5、值 (ID) = 12345,依此类推
再次回到我需要的,这家伙/TlvEncoding 如何压缩长度以允许存储超过 4 个字节。例如,带有 AND 或二进制逻辑运算符的 AND 或二进制逻辑运算符:
假设我有长度为 1000 的字符串,超过 1 个字节。他做以下
注意:0xffff = 65,535 或的最大值。我认为长度 1000 将在那条线上相遇时的条件。stream 将写入 2 个字节的长度。但是当他读到这个值时,他会做更多的逻辑操作。这已经泄漏了。:(UInt16
ushort
/// <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);
}
}
在读取操作中,他做:(我认为条件会在这里满足)
我不知道他为什么选择等于 127 0x7f,然后0x80等于 128 中删除。0x7f; // remove 0x80 bit
/// <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;
}
请我只需要了解那里的情况,因为我需要在字节数组中应用相同的方法。我需要存储 i.e:长度为 1500 的字符串、日期时间、一些整数,如 (TLV)。但我所知道的是如何只应用 1 个字节长度 (255)。
所以我只能读取 1 个字节的长度,因为我不知道如何判断数组我需要寻找 3 个字节的长度?还是 2 个字节?然后,我必须存储所有 2 或 3 个字节的 TLV。这是浪费空间。
- 整数存储为 4 个字节(OK),所以我可以写 Length 是(注意字节强制转换)
(byte) 4
- 字符串只能存储在 255 中,但是如何像上面一样做到这一点呢?1500 个字节的长度?
简单地说,我解释一下,他允许存储 1 个字节作为长度,有时存储 3 个字节作为长度。我什至不知道他如何告诉编译器/流从接下来的 3 个字节读取此标签长度。或接下来的 2 个字节。或 1 字节。
答:
从 来看,它看起来相当简单。WriteLength
介于 0 和 0x7F 之间的值仅由具有该值的单个字节表示。因此,如果你想写例如值,你写一个带有值的字节。5
5
对于> 0x7F值:
- 第一个字节是表示值所需的字节数,设置了最高位(以便您可以分辨它与值介于 0-127 之间的简单字节之间的区别)
- 接下来的字节数为实际值。
价值 | 序列 化 |
---|---|
0 | 0x00 |
1 | 0x01 |
127 | 0x7F |
128 | 0x81 0x80 |
129 | 0x81 0x81 |
255 | 0x81 0xFF |
256 | 0x82 0x01 0x00 |
257 | 0x82 0x01 0x01 |
65535 | 0x82 0xFF 0xFF |
65536 | 0x83 0x01 0x00 0x00 0x00 |
等等......
评论