元素,那么在解壓縮的時(shí)候,我們就可以根據(jù)off獲得待匹配字符串的指針,再將該指針指示的字符作為起點(diǎn),復(fù)制長度為Ien的字符串到當(dāng)前字符指針?biāo)甘镜目臻g,就可以獲得原始的輸入數(shù)據(jù)序列。因?yàn)檫@一段字符串在輸出序列中并不存在,是需要解碼然后再復(fù)制過來的,所以稱這段字符串為復(fù)制碼。復(fù)制碼可以用兩個(gè)元素off和Ien表不。
[0096]那么,我們的輸出序列,就變成(若干個(gè)原始碼,off,len)這樣的形式。因?yàn)槿舾蓚€(gè)原始碼,其長度并不固定,我們無法解析第幾個(gè)字節(jié)表示off和Ien的值,所以我們把輸出序列轉(zhuǎn)換一下,變成(off,lenC,lenL,若干個(gè)原始碼)這樣的形式。那么就便于以后的解壓縮的處理了。這其中,IenC即是復(fù)制碼的Ien元素,而IenL表示若干個(gè)原始碼的長度。
[0097]輸出(off, IenC, IenL,若干個(gè)原始碼)序列以后,將原始碼指針+lenC+lenL,重新賦值給原始碼指針。再令當(dāng)前字符指針等于重新賦值以后的原始碼指針。
[0098]然后,判斷當(dāng)前字符指針是否小于等于數(shù)據(jù)塊尾部偏移量,如果是,轉(zhuǎn)向步驟2繼續(xù)執(zhí)行,否則轉(zhuǎn)向步驟7。
[0099]5.如果匹配不成功,那么,令當(dāng)前字符指針加1,然后轉(zhuǎn)向步驟2繼續(xù)執(zhí)行。
[0100]6.執(zhí)行本步驟表示對(duì)數(shù)據(jù)塊的所有數(shù)據(jù)即將處理完畢。本步驟執(zhí)行以下操作,輸出(0,0,lenL,若干個(gè)原始碼)到輸出序列。其中的off和IenC元素的值都為0,表示只有原始碼,沒有復(fù)制碼。IenL的值應(yīng)該等于(數(shù)據(jù)塊尾部偏移量-原始碼指針+1),若干個(gè)原始碼的序列應(yīng)該是從原始碼指針處開始,直到數(shù)據(jù)塊最后一個(gè)字符處結(jié)束。然后繼續(xù)執(zhí)行步驟7。
[0101]7.對(duì)于輸出的(off, IenC, IenL,若干個(gè)原始碼)序列進(jìn)行分區(qū)編碼。
[0102](I)分區(qū)編碼的具體處理方法:
[0103]為了便于計(jì)算機(jī)快速處理數(shù)據(jù),我們將(off,IenC, lenL,若干原始碼)序列進(jìn)行分區(qū)處理。
[0104]首先,連續(xù)存放的壓縮碼表現(xiàn)為如下形式:
[0105]壓縮碼序列1:
[0106](offl, IenCl, IenLl) +(若干原始碼 I) ; (off2, lenC2, lenL2) + (若干原始碼 2);(off3, lenC3, lenL3) + (若干原始碼 3)...
[0107]可以看見壓縮碼序列I是連續(xù)存放,三元組(off, IenCl, IenLl)和(若干原始碼)連續(xù)存放,不利于計(jì)算機(jī)進(jìn)行快速處理。
[0108]本方法將壓縮碼序列I分區(qū)進(jìn)行存放,具體方法如下:
[0109]壓縮碼序列I轉(zhuǎn)化為壓縮碼序列2:
[0110]壓縮碼序列2:
[0111]分區(qū)a:
[0112](offl, IenCl, IenLl) ; (off2, lenC2, lenL2) ; (off3, lenC3, lenL3)
[0113]分區(qū)b:
[0114]若干原始碼I ;若干原始碼2 ;若干原始碼3
[0115]整個(gè)壓縮碼序列2由分區(qū)a和分區(qū)b組成,分區(qū)a僅僅存放三元組序列,分區(qū)b單獨(dú)存放原始碼序列,通過分區(qū)編碼,將不同屬性的數(shù)據(jù)分區(qū)存放,便于計(jì)算機(jī)更加高效的處理數(shù)據(jù)。
[0116](2)分區(qū)編碼算法的進(jìn)一步優(yōu)化
[0117]經(jīng)過上述步驟編碼以后的壓縮碼序列,已經(jīng)將不同屬性數(shù)據(jù)分區(qū)存放,其中分區(qū)a存放三元組(off, IenC, lenL)序列,分區(qū)b存放原始碼序列。為了進(jìn)一步優(yōu)化,可以將分區(qū)a進(jìn)行二次壓縮和二次編碼,經(jīng)過二次編碼以后形成的數(shù)據(jù)可以再一次分區(qū)成d和C,即分區(qū)c和分區(qū)d為分區(qū)a的子分區(qū),二者共同構(gòu)成分區(qū)a。
[0118](3)分區(qū)編碼算法的數(shù)據(jù)結(jié)構(gòu)具體定義及編碼方法
[0119]分區(qū)編碼算法的數(shù)據(jù)結(jié)構(gòu)分為兩種定義,分別定義了快速編碼算法和緊湊編碼算法。
[0120]由于輸入數(shù)據(jù)流最大為64KB,所以(off,IenC, lenL)三元組中的off元素,最大為65535,不會(huì)超出2個(gè)字節(jié)表示范圍。以下的數(shù)據(jù)結(jié)構(gòu)定義都默認(rèn)基于大端模式。
[0121](3.1)
[0122]快速編碼算法編碼壓縮步驟及結(jié)構(gòu)定義:
[0123]定義臨時(shí)區(qū)的單個(gè)三元組表項(xiàng)結(jié)構(gòu)為4字節(jié)結(jié)構(gòu),其中off元素以2字節(jié)表示,IenC和IenL分別以I字節(jié)表示,整個(gè)臨時(shí)區(qū)由若干個(gè)連續(xù)的三元組表項(xiàng)組成。
[0124]由于我們在前述的壓縮過程中,在進(jìn)行字符串匹配的時(shí)候,是至少要匹配4個(gè)字符才輸出三元組序列,所以其中的IenC表示復(fù)制碼長度,必然是大于等于4的,所以我們先進(jìn)行一個(gè)臨時(shí)變量的替換。
[0125]$T_lenC = lenC-4,用T_lenC替換掉三元組序列中的IenC元素,得到新的三元組序列(off,T_lenC,IenL)……以下我們進(jìn)行編碼時(shí)都是處理新的(off,T_lenC,IenL)三元組,而解碼時(shí),可以獲得T_lenC的值,再+4即得到復(fù)制碼的長度,即IenC的值。
[0126]現(xiàn)假設(shè)經(jīng)過字符串匹配算法已經(jīng)獲得了三元組序列
[0127](offl, T_lenCl, IenLl) (off2, T_lenC2, lenL2) (off3, T_lenC3, lenL3)...,對(duì)于一個(gè)三元組(off,T_lenC,lenL),其中的off元素經(jīng)前述分塊處理后,可以用2字節(jié)表示,不會(huì)出現(xiàn)溢出情況。而對(duì)于T_lenC,IenL元素,我們在臨時(shí)區(qū)給其分配的結(jié)構(gòu)為每個(gè)元素僅占I個(gè)字節(jié),I個(gè)字節(jié)表示T_lenC和IenL最大值只能為255,而有可能出現(xiàn)T_lenC或者IenL的值大于255的情況,那么我們就需要對(duì)(off, T_lenC, lenL)進(jìn)行一個(gè)預(yù)處理。
[0128]預(yù)處理:
[0129]如果T_lenC> = 255 且 lenL〈255,那可以令(off, T_lenC, lenL)轉(zhuǎn)換為(off, 255,lenL)+4字節(jié)的形式,后續(xù)追加的4字節(jié)表示(T_lenC_255)的值。
[0130]如果lenL> = 255 且 T_lenC<255,那可以令(off, T_lenC, lenL)轉(zhuǎn)換為(off, T_lenC,255)+4字節(jié)的形式,后續(xù)追加的4字節(jié)表示(lenL-255)的值。
[0131]如果T_lenC> = 255 且 lenL> = 255,那可以令(off, T_lenC, lenL)轉(zhuǎn)換為(off, 255,255)+4字節(jié)+4字節(jié)的形式,后續(xù)追加的第一個(gè)4字節(jié)表示(T_lenC_255)的值,第二個(gè)4字節(jié)表示(lenL-255)的值。
[0132]這樣,經(jīng)過預(yù)處理以后,三元組序列
[0133](offl, T_lenCl, IenLl) (off2, T_lenC2, lenL2) (off3, T_lenC3, lenL3)...
[0134]可能轉(zhuǎn)換成類似
[0135](offl, T_lenCl, 255) (lenLl-255) (off2, T_lenC2, lenL2) (off3, T_lenC3, lenL3)...的形式,
[0136]我們稱其中混雜的(T_lenC-255)或者(lenL-255)這些項(xiàng)目為偽三元組,在整個(gè)序列中,可能沒有偽三元組,也可能存在若干個(gè)偽三元組,但是不影響后續(xù)操作,因?yàn)槿M和偽三元組都是占用4個(gè)字節(jié)。我們將經(jīng)過預(yù)處理以后的三元組序列存放在臨時(shí)區(qū)。
[0137]對(duì)于臨時(shí)區(qū)的三元組和偽三元組混合序列,現(xiàn)在進(jìn)行二次壓縮編碼,將其分別生成c區(qū)編碼和d區(qū)編碼,c區(qū)和d區(qū)為a區(qū)的子分區(qū),二者共同構(gòu)成a區(qū)。
[0138]臨時(shí)區(qū)二次壓縮方法如下:
[0139]對(duì)于一個(gè)三元組(off, T_lenC, lenL)(或偽三元組,一樣將其占用的4字節(jié)視作有3個(gè)元素),其長度為4字節(jié),現(xiàn)將其用2個(gè)三元組表示,第一個(gè)三元組(a,b, c)為壓縮前綴,第二個(gè)三元組(X,y, z)為短碼本體。三元組(a, b, c)是一個(gè)固定長度編碼,固定為a占用2位,b占用I位,c占用I位,所以三元組(a, b, c) 一共占用4位。而三元組(x, y, z)為可變長編碼,X可以為16位,12位,8位,4位長度,y可以為8位或4位長度,z可以為8位或4位長度,所以三元組(X,y, z)的長度可能在12位到32位之間變化。三元組(a, b, c)和三元組(X,y, z)的各個(gè)元素配對(duì)編碼表示三元組(off, T_lenC, IenL)的三個(gè)元素。具體定義為:a+x編碼off, b+y編碼T_lenC, c+z編碼lenL,其中a為2位標(biāo)志位,若a = 0,表示X占用4位,若a = 1,表示X占用8位,若a = 2,表示x占用12位,若a = 3,表示X占用16位。b為I標(biāo)志位,若b = O,表示y占用4位,若b = 1,表示y占用8位。c為I位標(biāo)志位,若C = O,表示Z占用4位,若C = 1,表示Z占用8位。壓縮時(shí),根據(jù)(off, T_IenC, lenL)的三個(gè)元素的具體值,將其轉(zhuǎn)換為(x,y,z)可變長度三元組和(a,b,c)三元組前綴,即
[0140]若off〈16,那么用4位X表示off的值,且令a = O ;
[0141]若16〈 = off〈256,那么用8位x表示off的值,且令a = I ;
[0142]若256〈 = off〈4096,那么用12位x表示off的值,且令a = 2 ;
[0143]若4096〈 = off〈65535,那么用16位x表示off的值,且令a = 3 ;
[0144]^T_lenC<16,那么用4位y表示T_lenC的值,且令b = O ;
[0145]若T_lenC> = 16,那么用8位y表示T_lenC的值,且令b = I ;
[0146]若lenL〈16,那么用4位z表示IenL的值,且令c = O ;
[0147]若lenL> = 16,那么用8位z表示IenL的值,且令c = I ;
[0148]這樣,就可以把三元組(off, T_lenC, lenL)轉(zhuǎn)換為2個(gè)三元組(a, b,c)和(X,y, z),且大多數(shù)情況下,三元組(a, b, c) +三元組(x, y, z)的長度要小于三元組(off, T_IenC, lenL)的長度,這樣就達(dá)到了壓縮三元組(off, T_lenC, lenL)的目的。
[0149]在解壓縮的時(shí)候,先取得三元組(a,b,c)的具體值,然后就能明確知道可變長度三元組(X,y, Z)的準(zhǔn)確長度,然后解析出X,y, Z各個(gè)元素的準(zhǔn)確值。需要注意的是,即使是對(duì)于偽三元組,也可以用(a,b,c)和(x,y,z)來進(jìn)行二次壓縮編碼,因?yàn)閭稳M也是正好占用四個(gè)字節(jié)。
[0150]對(duì)所有的三元組(off,T_lenC,IenL)完成編碼以后,形成了 c區(qū)數(shù)據(jù)序列和d區(qū)數(shù)據(jù)序列,c區(qū)和d區(qū)共同構(gòu)成a區(qū)。
[0151]需要注意的是,具體的計(jì)算機(jī)存儲(chǔ)方式有大端模式和小端模式之分,因而在壓縮數(shù)據(jù)處理完畢后,會(huì)生成一個(gè)標(biāo)志來表示是大端模式還是小端模式,本方法此前的描述都是基于大端模式的。本方法也可以適用于小端模式,對(duì)于小端模式計(jì)算機(jī),可以將數(shù)據(jù)結(jié)構(gòu)前后顛倒,處理順序也前后顛倒,即從分區(qū)末尾往前處理即可。
[0152]經(jīng)過以上的二次壓縮編碼,分區(qū)a被分割成了 c區(qū)和d區(qū)兩個(gè)子分區(qū),c區(qū)和d區(qū)的數(shù)據(jù)可以組合起來解析出完整的a區(qū)數(shù)據(jù)。
[0153]在二次壓縮完成以后,生成分區(qū)c和分區(qū)d,并且一定要在a區(qū)頭部生成若干個(gè)標(biāo)志字節(jié),記錄分區(qū)c和分區(qū)d的長度、起始位置、大端模式、小端模式和其他屬性。
[0154](3