你所看到的是AmfInteger
字節的字符串表示形式。第一個例子,\xa2C
包括兩個字節:0xa2
又名162,和C
,這是67 ASCII表示:
>>> ord("\xa2C"[0])
162
>>> ord("\xa2C"[1])
67
將其轉換成AmfInteger,我們也要跟着AMF3 specifications,第1.3.1節(AmfInteger的格式在AMF0和AMF3中是相同的,所以我們看什麼規格都沒有關係)。
在該部分中,U29(可變長度無符號29位整數,這是AmfIntegers在內部用於表示值的值)被定義爲1,2,3或4字節序列。每個字節對關於值本身的信息進行編碼,以及是否接着另一個字節。爲了弄清楚另一個字節是否符合當前的,一個只需要檢查最顯著位是否被設置:
>>> (162 & 0x80) == 0x80
True
>>> (67 & 0x80) == 0x80
False
所以我們現在證實了,你看到的字節序列的確是一個充滿U29:第一個字節有它的高位設置,表示它後面跟着另一個字節。第二個字節的位未設置,表示序列結束。爲了充分利用這些字節的實際價值,我們現在只需要他們的價值觀結合起來,同時掩蓋了第一個字節的最高位:
>>> 162 & 0x7f
34
>>> 34 << 7
4352
>>> 4352 | 67
4419
從這一點應該很容易明白,爲什麼其他值給出你觀察到的結果。
爲了完整起見,這裏也是一個Python代碼段與解析U29,包括所有的角落案件的範例:
def parse_u29(byte_sequence):
value = 0
# Handle the initial bytes
for byte in byte_sequence[:-1]:
# Ensure it has its high bit set.
assert ord(byte) & 0x80
# Extract the value and add it to the accumulator.
value <<= 7
value |= ord(byte) & 0x7F
# Handle the last byte.
value <<= 8 if len(byte_sequence) > 3 else 7
value |= ord(byte_sequence[-1])
# Handle sign.
value = (value + 2**28) % 2**29 - 2**28
return value
print parse_u29("\xa2C"), 4419
print parse_u29(map(chr, [0x88, 0x00])), 1024
print parse_u29(map(chr, [0xFF, 0xFF, 0x7E])), 0x1ffffe
print parse_u29(map(chr, [0x80, 0xC0, 0x80, 0x00])), 0x200000
print parse_u29(map(chr, [0xBF, 0xFF, 0xFF, 0xFE])), 0xffffffe
print parse_u29(map(chr, [0xC0, 0x80, 0x80, 0x01])), -268435455
print parse_u29(map(chr, [0xFF, 0xFF, 0xFF, 0x81])), -127
'a2C'不是4419十進制無論是。我注意到'C'是大寫的,(就像下一行的'I')。 –
謝謝!我更新了這個問題! – wu4m4n
你如何得到這些值?他們來自哪裏?我沒有看到AMF使用'\ x'前綴的證據,所以我懷疑你正在看Python * repr()'output *,其中可打印的ASCII字符就是這樣表示的。 –