╔════════════╦═══════════════╦═══════════════════╗
║ first byte ║ optional byte ║ UTF-8 string data ║
╚════════════╩═══════════════╩═══════════════════╝
标头中的第二个字节是可选的,仅在需要UTF-8字符串时才存在超过128个字节要存储。当字符串长度小于或等于128个字节时,解码它的长度很容易。但是,当字符串长度> 128时,我无法从标题部分计算字符串长度。因此,我进行了实验,并生成了许多具有不同字符串长度的二进制文件,结果如下。字符串长度是存储字符串所需的字节总数。第一列和第二列是标头部分中的第一和第二个可选字节。
我的问题是,如何使用标头部分中的值计算长度大于128个字节的字符串长度? >
#1 楼
这不是pascal / delphi字符串格式,因为它们是恒定的1字节或4字节长的字段。它确实与ASN1格式有些相似,除了ASN1带有一个附加字段表示
总的来说,这看起来像第一个字节的最高有效位不是长度的一部分,并且具有将长度再增加一个字节的特殊含义。
如果使用该表:
In [24]: t
Out[24]:
[['7D', 'N/A', '126'],
['7E', 'N/A', '127'],
['7F', 'N/A', '128'],
['80', '01', '129'],
['81', '01', '130'],
['C7', '01', '200'],
['C8', '01', '201'],
['F9', '01', '250'],
['FE', '01', '255'],
['FF', '01', '256'],
['80', '02', '257'],
['81', '02', '258'],
['82', '02', '259'],
['F3', '03', '500'],
['F4', '03', '501'],
['F5', '03', '502'],
['F6', '03', '503'],
['80', '04', '513']]
,将MSB拆分为第一个字节:
首先,请注意
0x7D
是十进制的125,而不是126。这对于MSB清除的所有值都是正确的,因此所有这些值总是加一。然后如果设置了MSB,第二个字节中的值乘以128,然后加到第一个字节的结果中。
下面的示例使用前两个字节来计算结果(并将其附加为最后一个字节)值:
In [36]: t2=[[int(l[0], 16)&0b10000000>0, hex(int(l[0], 16)&0b01111111)[2:]]+l[1:] for l in t]
In [37]: t2
Out[37]:
[[False, '7d', 'N/A', '126'],
[False, '7e', 'N/A', '127'],
[False, '7f', 'N/A', '128'],
[True, '0', '01', '129'],
[True, '1', '01', '130'],
[True, '47', '01', '200'],
[True, '48', '01', '201'],
[True, '79', '01', '250'],
[True, '7e', '01', '255'],
[True, '7f', '01', '256'],
[True, '0', '02', '257'],
[True, '1', '02', '258'],
[True, '2', '02', '259'],
[True, '73', '03', '500'],
[True, '74', '03', '501'],
[True, '75', '03', '502'],
[True, '76', '03', '503'],
[True, '0', '04', '513']]
上面计算的代码不是很漂亮,所以这是一个简短的python函数,其功能相同:
In [53]: t3 = [l+[int(l[1], 16) + 1 + (int(l[2], 16)*128 if l[0] else 0)] for l in t2]
In [54]: t3
Out[54]:
[[False, '7d', 'N/A', '126', 126],
[False, '7e', 'N/A', '127', 127],
[False, '7f', 'N/A', '128', 128],
[True, '0', '01', '129', 129],
[True, '1', '01', '130', 130],
[True, '47', '01', '200', 200],
[True, '48', '01', '201', 201],
[True, '79', '01', '250', 250],
[True, '7e', '01', '255', 255],
[True, '7f', '01', '256', 256],
[True, '0', '02', '257', 257],
[True, '1', '02', '258', 258],
[True, '2', '02', '259', 259],
[True, '73', '03', '500', 500],
[True, '74', '03', '501', 501],
[True, '75', '03', '502', 502],
[True, '76', '03', '503', 503],
[True, '0', '04', '513', 513]]
看一下它,可能更直观,它是第二个字节是第一个字节的7位(MSB除外)的延续。 /> def calc(first_byte, second_byte):
value = 1
value += first_byte & 0x7F
msb = bool(first_byte >> 7)
if msb:
value += second_byte * 128
我们缺少在第二个字节上设置了MSB的任何值,但是这种方法可能是顺序的,通过设置所有先前MSB的MSB可以使用更大的范围个字节。
#2 楼
看起来像LEB128
编码。 本质上,这是一种可变长度编码,其中每个字节的最低7位存储值的一部分,如果不是最后一个字节,则设置每个字节的最高位字节。连续的7位值以小端顺序存储。有关更多详细信息,尤其是有关如何处理带符号数字的详细信息,请参阅DWARF调试标准或Android DEX文件格式文档。
这类似于MIDI文件和ASN.1编码中使用的可变长度数量格式,该格式使用大端顺序。 br />