3
我有一個字節流,它是一個串聯的節,其中每個節由一個頭和一個放縮的字節流組成。如何超越字節流中包含的放氣字節序列?
我需要分割這個字節流部分,但頭只包含有關未壓縮形式的數據的信息,沒有關於壓縮數據長度的提示,所以我可以在流中正確前進並解析下一部分。
到目前爲止,我發現超越癟縮字節序列的唯一方法是根據this specification解析它。根據我所瞭解的規範,deflate流由塊組成,可以是壓縮塊或文字塊。
文字塊包含一個大小標題,可用於輕鬆超越它。
壓縮塊由'前綴代碼'組成,它是可變長度的位序列,對縮放算法有特殊的含義。由於我只想找出縮小的流長度,所以我想我需要查找的唯一代碼是'0000000',根據規範指示塊結束。
所以我想出了這個CoffeeScript的函數來解析放氣流(我工作的node.js)
# The job of this function is to return the position
# after the deflate stream contained in 'buffer'. The
# deflated stream begins at 'pos'.
advanceDeflateStream = (buffer, pos) ->
byteOffset = 0
finalBlock = false
while 1
if byteOffset == 6
firstTypeBit = 0b00000001 & buffer[pos]
pos++
secondTypeBit = 0b10000000 & buffer[pos]
type = firstTypeBit | (secondTypeBit << 1)
else
if byteOffset == 7
pos++
type = buffer[pos] & (0b01100000 >>> byteOffset)
if type == 0
# Literal block
# ignore the remaining bits and advance position
byteOffset = 0
pos++
len = buffer.readUInt16LE(pos)
pos += 2
lenComplement = buffer.readUInt16LE(pos)
if (len^~lenComplement)
throw new Error('Literal block lengh check fail')
pos += (2 + len) # Advance past literal block
else if type in [1, 2]
# huffman block
# we are only interested in finding the 'block end' marker
# which is signaled by the bit string 0000000 (256)
eob = false
matchedZeros = 0
while !eob
byte = buffer[pos]
for i in [byteOffset..7]
# loop the remaining bits looking for 7 consecutive zeros
if (byte^(0b10000000 >>> byteOffset)) >>> (7 - byteOffset)
matchedZeros++
else
# reset counter
matchedZeros = 0
if matchedZeros == 7
eob = true
break
byteOffset++
if !eob
byteOffset = 0
pos++
else
throw new Error('Invalid deflate block')
finalBlock = buffer[pos] & (0b10000000 >>> byteOffset)
if finalBlock
break
return pos
要檢查,如果這個工程,我寫了一個簡單的摩卡測試用例:
zlib = require 'zlib'
test 'sample deflate stream', (done) ->
data = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' # length 30
zlib.deflate data, (err, deflated) ->
# deflated.length == 11
advanceDeflateStream(deflated, 0).shoudl.eql(11)
done()
問題是,此測試失敗,我不知道如何調試它。我接受任何答案,指出我在解析算法中遺漏了什麼,或者是否包含任何語言的上述函數的正確版本。
我認爲前綴代碼背後的想法是,沒有代碼可能是另一個代碼的前綴,如果是的話,塊結束標記怎麼會出現在塊結束?代碼解析算法是否在前方? –
是的,沒有代碼是另一個代碼的前綴。但是,這並不妨礙代碼出現在兩個其他代碼的位的結合中。前綴屬性僅適用於您知道每個代碼開始的位。爲了知道代碼在哪一位開始,你需要先解碼所有的代碼。 –
明白了,謝謝。 –