prakti na uporaba algoritmov stiskanja podatkov · na koncu si bomo ogledali še huffmanovo...
Post on 19-Oct-2020
2 Views
Preview:
TRANSCRIPT
UNIVERZA V MARIBORU
FAKULTETA ZA ELEKTROTEHNIKO, RA�UNALNIŠTVO IN
INFORMATIKO
Janko HERLAH
PRAKTI�NA UPORABA ALGORITMOV STISKANJA
PODATKOV
Diplomska naloga
Maribor, Julij 2009
I
UNIVERZA V MARIBORU
FAKULTETA ZA ELEKTROTEHNIKO, RA�UNALNIŠTVO IN INFORMATIKO 2000 Maribor, Smetanova ul. 17
Diplomska naloga univerzitetnega študijskega programa
PRAKTI�NA UPORABA ALGORITMOV STISKANJA
PODATKOV
Študent: Janko HERLAH
Študijski program: Univerzitetni, ra�unalništvo in informatika
Smer: Programska oprema
Mentor: red. prof. dr. Borut ŽALIK
Maribor, Julij 2009
III
PRAKTI�NA UPORABA ALGORITMOV STISKANJA
PODATKOV
Klju�ne besede: algoritmi, brezizgubno stiskanje podatkov, algoritem
Deflate, kode CRC, vmesnik IMAPI
UDK: 004.627 (043.2)
Povzetek
V diplomskem delu smo izdelali in opisali aplikacijo za arhiviranje podatkov.
Opisali smo algoritme za brezizgubno stiskanje podatkov RLE, LZ77 in
Huffmanovo kodiranje, strukturo datoteke ZIP ter algoritem Deflate. Prav tako
razložimo teoreti�ne osnove ra�unanja kode CRC. Za zapisovanje na medije
CD/DVD smo uporabili programski vmesnik IMAPI ter opisali njegovo uporabo.
IV
PRACTICAL USE OF DATA COMPRESSION
ALGORITHMS
Keywords: algorithms, lossless data compression, algorithm
Deflate, CRC codes, IMAPI interface
UDK: 004.627 (043.2)
Abstract
As a result of the diploma thesis, a data archiving program is described. Firstly,
a ZIP file structure is explained and some lossless data compression algorithms
are presented: RLE, LZ77, Huffman coding and Deflate. Additionally, theoretical
principles of CRC arithmetics are introduced. For staging and burning image files
to CD/DVD optical media, an IMAPI programming interface is used and a very
simplified procedure for CD/DVD burning is provided.
V
VSEBINA
1 UVOD................................................................................................................ 1
2 PREDSTAVITEV ALGORITMOV STISKANJA ................................................. 5
2.1 Algoritem RLE ...................................................................................... 5
2.2 Algoritem LZ77 ..................................................................................... 6
2.3 Huffmanovo kodiranje........................................................................... 9
3 ALGORITEM DEFLATE.................................................................................. 15
3.1 Na�ini kodiranja.................................................................................. 19
3.2 Dinami�ne kodne tabele ..................................................................... 23
4 STRUKTURA DATOTEKE ZIP ....................................................................... 28
5 KODA CRC..................................................................................................... 34
6 IMAPI .............................................................................................................. 42
6.1 Znani problemi.................................................................................... 43
6.2 Vmesniki IMAPI .................................................................................. 45
7 PROGRAM ..................................................................................................... 51
7.1 Razredni diagrami .............................................................................. 51
7.2 Predstavitev delovanja programa ....................................................... 57
7.3 Parametri za samodejni zagon ........................................................... 63
8 ZAKLJU�EK ................................................................................................... 65
LITERATURA....................................................................................................... 67
PRILOGA A: Seznam slik..................................................................................... 68
PRILOGA B: Seznam tabel .................................................................................. 69
PRILOGA C: Vsebina zgoš�enke......................................................................... 70
Prakti�na uporaba algoritmov stiskanja podatkov 1
1 UVOD
V diplomskem delu bomo prikazali prakti�no uporabo nekaterih algoritmov
stiskanja podatkov. V ta namen bomo napisali program, ki bo omogo�al
arhiviranje. Arhiviranje bo možno izvesti ro�no ali samodejno ob prej nastavljenem
�asu. Datoteke bomo kodirali z algoritmom Deflate ([1], [2], [3] in [4]), rezultat pa
zapisali v arhiv ZIP ([5]). Za arhiv ZIP smo se odlo�ili, ker je najbolj razširjen
format arhivskih datotek in ga je možno odpreti tudi z drugimi programi. Program
bomo nadgradili še z dodatnimi možnostmi kot so: obnovitev podatkov iz arhiva in
zapisovanje na medije CD in DVD.
Proces stiskanja podatkov pretvarja poljubno vhodno zaporedje znakov v
kodirano izhodno zaporedje, ki pa je manjše po velikosti. Ta trditev v splošnem
velja, poznamo pa tudi algoritme, ki lahko v posebno neugodnih primerih tvorijo
daljše izhodno zaporedje. Takšnemu pojavu pravimo negativno stiskanje in se mu
poskušamo izogniti. Omenimo tudi, da ne obstaja algoritem, ki bi vse vrste
podatkov stisnil optimalno. Nekateri postopki so boljši za stiskanje slik, drugi za
stiskanje besedila, spet tretji za stiskanje zvoka ali videa itd.
U�inkovitost algoritma merimo z razmerjem stiskanja. Razmerje stiskanja
definiramo kot razmerje med velikostjo kodiranega in originalnega zaporedja.
Stiskanje dosežemo, �e je razmerje stiskanja manjše od ena.
Razmerje stiskanja = zaporedja vhodnega velikost
zaporedja kodiranega izhodnega velikost (1.1)
Ko razmišljamo, kako bi �imbolj optimalno stisnili podatke, se nam takoj
prikrade vprašanje: ali lahko izboljšamo stisljivost že samo s tem, �e stisnjene
datoteke stisnemo še enkrat? Odgovor je: NE. Stisnjene datoteke imajo ni� ali zelo
malo odve�ne informacije, saj je bila odstranjena v prvem postopku stiskanja, zato
Prakti�na uporaba algoritmov stiskanja podatkov 2
ni ve� kaj odvzeti. Lahko pa na vprašanje odgovorimo tudi intuitivno. �e bi lahko
stiskali že stisnjene datoteke, bi vsak nadaljni postopek stiskanja še dodatno
zmanjšal velikost datoteke. Postopek bi ponavljali poljubno dolgo, dokler ne bi na
koncu dobili zelo majhno datoteko, npr. dolžine enega zloga (angl. byte). To pa je
nesmisel, saj v en zlog ne moremo shraniti informacijo, ki jo vsebuje poljubno
dolga datoteka.
Kako torej dosežemo stiskanje? Vsako zaporedje znakov, ne glede na to, ali
predstavlja sliko, zvok ali kaj drugega, lahko vsebuje odve�no informacijo, ki jo
imenujemo redundanca. �e odve�no informacijo odstranimo, dobimo zaporedje, ki
je manjše po velikosti. Da dobimo �imbolj optimalen rezultat, izhodno zaporedje
kodiramo. Simbolom, ki se v zaporedju pojavljajo velikokrat, dodelimo �im krajše
kode. Simboli, ki se pojavijo redko, lahko imajo daljše kode, ker ne bodo bistveno
vplivali na velikost izhodnega niza. Za proces kodiranja potrebujemo kodirnik
(angl. encoder), za obratni proces dekodiranja, ki nam iz kodiranega niza vrne
original, pa dekodirnik (angl. decoder). Lastnosti obeh so dolo�ene z izbranim
algoritmom stiskanja.
Podrobna predstavitev nekaterih algoritmov stiskanja bo predstavljena v
drugem poglavju. Najprej bomo opisali algoritem RLE (angl. Run-Length
Encoding), ki daje dobre rezultate pri ponavljajo�ih se vrednostih. Kadar se nek
znak vhodnega zaporedja ponovi n-krat, v izhodno zaporedje zapišemo en sam
znak in njegovo število ponovitev. Sledil bo opis algoritma LZ77 (angl. Sliding
Window). Osnovna ideja algoritma je, da del vhodnega niza, ki smo ga že obdelali,
uporabimo kot slovar. Ko �itamo vhodni niz znak za znakom, poskušamo v
slovarju najti enak niz. V izhodni niz zapišemo troj�ek (odmik od konca slovarja,
dolžina ujemanja, znak). Algoritem daje tem boljše rezultate, �e uspemo v slovarju
najti dolge nize. Na koncu si bomo ogledali še Huffmanovo kodiranje. Huffmanovo
kodiranje je zelo priljubljeno, ker generira najbolj optimalne kode – simbolom, ki
nastopajo najve�krat, dodeljuje najkrajše kode. Slaba stran algoritma je, da
zahteva veliko korakov. V prvem koraku ugotovi verjetnosti pojavljanja
posameznih simbolov. Nato gradi binarno drevo tako, da v vsakem koraku poiš�e
Prakti�na uporaba algoritmov stiskanja podatkov 3
dva simbola A in B z najmanjšo verjetnostjo pojavljanja in ju združi v nov simbol
AB. Nov simbol vstavi v seznam, znaka A in B pa odstrani iz seznama. Tako se
seznam z vsakim korakom skr�i za en element. Postopek je kon�an, ko v
seznamu ostane samo en element, ki predstavlja koren Huffmanovega drevesa.
Vsako vozliš�e drevesa prispeva en bit v kodi posameznega simbola.
V tretjem poglavju bomo uporabili vse znanje iz drugega poglavja in opisali
algoritem Deflate, ki spada v skupino algoritmov brez izgub. Napisal ga je Philip
W. Katz. Njegov originalni algoritem je patentno zaš�iten, vse ostale razli�ice pa
so v javni lasti (angl. public domain). Je splošno namenski algoritem, primeren za
stiskanje vseh vrst podatkov, zato ga danes sre�amo v mnogih priljubljenih
programih, kot so:
• WinZip in Gzip: programa za arhiviranje podatkov
• operacijski sistem Windows™: od Windows XP dalje se uporablja za
arhiviranje (stisnjene mape in datoteke)
• format Adobe PDF: format za opis dokumentov
• protokol HTTP: protokol, ki nam omogo�a brskanje po internetu
• format PNG: vrsta zapisa slike
• Zlib: knjižnica, ki sta jo razvila Jean-Loup Gailly in Mark Adler in jo
razvijalci lahko prosto uporabijo v svojih aplikacijah itd.
V �etrtem poglavju bomo opisali osnovno strukturo datoteke ZIP, zato se ne
bomo spuš�ali v vse podrobnosti specifikacije. Želimo dose�i zapisovanje v arhiv
in branje iz njega. Eden izmed pomembnejših podatkov v arhivu ZIP je koda CRC
([6] in [7]), ki jo moramo priložiti k vsaki stisnjeni datoteki. Služi za odkrivanje
napak v arhivu (ali je bila datoteka spremenjena). Ker so datoteke kodirane, lahko
že sprememba enega bita povzro�i, da datoteke ni možno odkodirati. Generiranje
kode CRC bo opisano v petem poglavju.
V šestem poglavju bomo opisali programski vmesnik IMAPI (angl. Image
Mastering API) in njegovo uporabo. IMAPI ([8]) služi za zapisovanje na medije
Prakti�na uporaba algoritmov stiskanja podatkov 4
CD/DVD. Od Windows XP dalje je del Microsoftovih operacijskih sistemov.
Omogo�a zelo natan�no kontrolo nad procesom zapisovanja podatkov, saj
vsebuje kar osemintrideset vmesnikov (angl. Interface). Opisan bo postopek, kako
v program dodamo funkcionalnost, ki jo nudi IMAPI. Opisani bodo tudi najvažnejši
vmesniki in njihove metode.
V sedmem poglavju bo predstavljena zgradba in delovanje programa. Program
omogo�a arhiviranje, obnovitev podatkov in zapisovanje na medije CD/DVD.
Opisani bodo najvažnejši razredi in metode. Predstavljen bo grafi�ni vmesnik
programa, s katerim upravljamo, ko se nahajamo v interaktivnem na�inu. Podali
bomo tudi opis ukaznih parametrov, s katerimi krmilimo program, ko se izvaja v
ozadju, brez posredovanja uporabnika.
Zaklju�ek bomo izkoristili za opis splošnih ugotovitev glede razvoja programa.
Nakazane bodo nekatere omejitve in možne rešitve.
Prakti�na uporaba algoritmov stiskanja podatkov 5
2 PREDSTAVITEV ALGORITMOV STISKANJA
V drugem poglavju bomo pripravili osnovo za opis algoritma Deflate.
Predstavljeni bodo trije algoritmi: RLE, LZ77 in Huffmanovo kodiranje. Za boljše
razumevanje bomo pri vsakem opisu podali tudi podroben primer.
2.1 Algoritem RLE
Ideja algoritma je zelo preprosta. Kadar se nek znak vhodnega zaporedja
ponovi n-krat, v izhodno zaporedje zapišemo dvoj�ek (število ponovitev, znak).
Oklepajev in vejic ne pišemo v izhodni kodirani niz, prikazujemo jih zaradi boljše
berljivosti. Edini problem pri takšnem kodiranju je, kako dekodirnik lo�i med
znakom in številom ponovitev. Rešitev je ve�, naštejmo jih samo nekaj.
Dodajanje posebnega znaka: izberemo katerikoli znak, ki ne nastopa v vhodnem
zaporedju in ga zapišemo pred številom ponovitev. Algoritem je neuporaben, �e
lahko v vhodnem zaporedju pri�akujemo celoten nabor znakov (noben znak ne
moremo »žrtvovati« kot poseben znak). Ker moramo v izhodni niz zapisati troj�ek
(poseben znak, število ponovitev, znak), lahko ta pristop uporabimo samo, �e se
znak ponovi vsaj trikrat.
Primer: kodirajmo vhodno zaporedje AAABCDDDDEEFFFFF. Za poseben znak si izberemo znak
@. Dobimo: @3ABC@4DEE@5F.
Zaporedje treh enakih znakov: ko kodirnik naleti na zaporedje vsaj treh enakih
znakov, v izhodni niz zapiše znak trikrat, ki pa mu takoj sledi preostalo število
ponovitev. Slaba stran tega pristopa je, da pri treh enakih znakih dosežemo
razširitev, stisljivost pa šele pri petih enakih znakih.
Prakti�na uporaba algoritmov stiskanja podatkov 6
Primer: kodirajmo vhodno zaporedje AAABCDDDDEEFFFFF.Dobimo: AAA0BCDDD1EEFFF2.
Uporaba kontrolnega zloga: kadar imamo vsaj tri enake zaporedne znake, jih v
izhodni niz zapišemo kot dvoj�ek (število ponovitev, znak), pri tem pa v kontrolnem
zlogu z ustreznim bitom ozna�imo, kje v naslednjih osmih zlogih se nahaja število
ponovitev. V izhodni niz najprej zapišemo kontrolni zlog, ki mu sledi osem
podatkovnih zlogov, nato sledi kontrolni zlog za naslednjih osem podatkovnih
zlogov itd. Na ra�un kontrolnih zlogov se izhodno zaporedje pove�a za 1/8 celotne
dolžine. Pri sodobnih ra�unalnikih lahko ta prirastek zmanjšamo z uporabo 32-
bitnih ali 64-bitnih kontrolnih zlogov.
Primer: kodirajmo vhodno zaporedje AAABCDDDDEEFFFFF.Dobimo: 100010002 3ABC4DEE 102
5F… Kontrolni zlog je prikazan kot binarno število. Iz bitov kontrolnega zloga lepo vidimo položaje
zlogov, ki ozna�ujejo število ponovitev.
2.2 Algoritem LZ77
Algoritem LZ77 je doživel mnogo sprememb. Številni avtorji so izboljšali
posamezne dele algoritma in tako ustvarili celo vrsto razli�ic kot so: LZX (Jonathan
Forbes), LZH (Bernd Herd), LZSS (Storer in Szymanski), LZFG (Edward Fiala in
Daniel Greene), LZRW1 in LZRW4 (Ross Williams), QIC-122 itd.
Mi se bomo osredoto�ili na osnovno izvedbo algoritma. Vhodni niz znakov, ki
jih želimo kodirati, razdelimo na dva dela. Leva stran je slovar (angl. dictionary) in
vsebuje znake, ki smo jih že kodirali. Na za�etku kodiranja je slovar prazen. Desna
stran predstavlja zaporedje znakov, ki jih še moramo obdelati. Iz desne strani po
vrsti jemljemo znake in iz njih tvorimo besedo, ki je najprej dolžine enega znaka,
nato dveh, treh itd. Besedo pove�ujemo z dodajanjem znakov dokler lahko v
slovarju najdemo ujemanje. Ko pridemo do besede, ki je ni v slovarju, v izhodno
zaporedje namesto besede zapišemo troj�ek (odmik od konca slovarja, dolžina
ujemanja, zadnji znak besede). Oklepajev in vejic ne pišemo v izhodni kodirani niz,
prikazujemo jih zaradi berljivosti. Na za�etku, ko je slovar majhen, ne najdemo
ujemanja niti za besede dolžine enega znaka, zato moramo v izhodno zaporedje
Prakti�na uporaba algoritmov stiskanja podatkov 7
zapisati troj�ek (0, 0, znak). Pravkar obdelano besedo nato pomaknemo na levo
stran v slovar. Algoritem daje tem boljše rezultate, �e uspemo v slovarju najti
dolge besede.
Primer: z algoritmom LZ77 kodirajmo stavek »Ra�unalnik ra�una …«. Na za�etku je slovar prazen.
R a � u n a l n i k r a � u n a ...slovar besedilo
Slika 2.2.1: Algoritem LZ77 (prazen slovar)
Obdelujemo R, prvo �rko besedila. Ker je slovar prazen, v izhodni niz zapišemo (0,0,R), �rko R pa
prestavimo v slovar.
R a � u n a l n i k r a � u n a ...slovar besedilo
Slika 2.2.2: Algoritem LZ77 (prvi korak)
Nadaljujemo z a, drugo �rko besedila. Ker v slovarju ne najdemo �rke a, v izhodni niz zapišemo
(0,0,a), �rko pa prestavimo v slovar. Podobno velja tudi za naslednje �rke: �, u, n. Ker v slovarju ne
najdemo ujemanja, v izhodni niz zapišemo (0,0,�), (0,0,u) in (0,0,n).
R a � u n a l n i k r a � u n a ...slovar besedilo
Slika 2.2.3: Algoritem LZ77 (po nekaj korakih)
Sedaj je spet na vrsti �rka a, ki se že nahaja v slovarju in sicer na odmiku 4 (slovar preiskujemo od
konca proti za�etku). Ker smo našli ujemanje, preberemo naslednjo �rko l, da dobimo besedo »al«
in pogledamo, ali na odmiku 4 najdemo ujemanje. Na tem mestu nimamo ujemanja, zato si
zapomnimo odmik 4 in dolžino ujemanja 1. Nato celoten postopek ponovimo od odmika 4 dalje. V
slovarju poskušamo najti naslednji a. Ker ga ne najdemo, v izhodni niz zapišemo (4,1,l), »al« pa
prestavimo v slovar.
Prakti�na uporaba algoritmov stiskanja podatkov 8
R a � u n a l n i k r a � u n a ...slovar besedilo
Slika 2.2.4: Algoritem LZ77 (nadaljevanje)
Tudi �rko n najdemo v slovarju, na odmiku 3, zato preberemo naslednjo �rko i, da dobimo besedo
»ni«. Ponovno preverimo, ali na odmiku 3 najdemo ujemanje za besedo »ni«. Ujemanja ni, zato si
zapomnimo odmik 3 in dolžino ujemanja 1 ter poskušamo v slovarju najti še kakšen n. Ker ga ne
najdemo, v izhodni niz zapišemo (3,1,i), »ni« pa prestavimo v slovar. �rke k ni v slovarju, zato jo
kodiramo kot (0,0,k). Podobno velja tudi za presledek: (0,0, ) in �rko r: (0,0,r).
R a � u n a l a � u n a ...slovar besedilo
n i k r
Slika 2.2.5: Algoritem LZ77 (zadnji korak)
Prišli smo do �rke a, ki jo v slovarju najdemo na odmiku 7. Ker smo našli ujemanje, pove�amo
besedo na »a�«. Na odmiku 7 nimamo ve� ujemanja za besedo »a�«, zato si zapomnimo odmik 7
in dolžino ujemanja 1 in v slovarju poskušamo najti še kakšen a. Naslednjo �rko a najdemo na
odmiku 11. Po vrsti beremo �rke u, n, a in za besede »a�u«, »a�un« in »a�una« vsaki� najdemo
ujemanje na odmiku 11. Na koncu pridemo do besede »a�una «, ki pa je ni v slovarju. Ker je
dolžina ujemanja daljša od tiste na odmiku 7, v izhodni niz zapišemo (11,5, ), besedo »a�una « pa
dodamo v slovar. Kon�ni izhodni niz se glasi: (0,0,R), (0,0,a), (0,0,�), (0,0,u), (0,0,n), (4,1,l), (3,1,i),
(0,0,k), (0,0, ), (0,0,r), (11,5, ).
Prednost zgornjega pristopa je v tem, da si vedno zapomnimo samo eno,
najdaljše ujemanje, s �imer privar�ujemo pri pomnilniku. �e se zgodi, da imamo
ve� ujemanj enake dolžine, v izhodni niz zapišemo tisto, ki smo ga našli nazadnje
(ki je najbolj oddaljeno od konca slovarja). Ker moramo vsaki� v izhodni niz
zapisati troj�ek (odmik, dolžina, znak), smo na zgornjem kratkem primeru dosegli
negativno stiskanje, t.j. izhodni niz je daljši od originala. V praksi pa imamo slovar
dolžine nekaj tiso� zlogov, zato je velika verjetnost, da bomo v slovarju našli
ujemanje daljših besed in tako dosegli boljše razmerje stiskanja. Omenimo še, da
Prakti�na uporaba algoritmov stiskanja podatkov 9
besedo, ki smo jo nazadnje obdelali, ne selimo fizi�no po pomnilniku iz desne na
levo stran v slovar, temve� si pomagamo s kazalcem, ki ozna�uje konec slovarja.
S pomikanjem kazalca v desno selimo besede v slovar. Ko smo obdelali celoten
vhodni niz, imamo dve možnosti: preberemo nove podatke in za�nemo s praznim
slovarjem. S tem bomo na za�etku postopka spet pridelali veliko troj�kov (0, 0,
znak), kar je slabo za u�inkovitost stiskanja. Boljši rezultat dosežemo, �e del
slovarja pomaknemo po pomnilniku v levo, ustrezno popravimo kazalec na konec
slovarja, preostanek pomnilnika pa napolnimo z novimi podatki.
2.3 Huffmanovo kodiranje
Je eden najbolj priljubljenih algoritmov za stiskanje podatkov. K priljubljenosti je
gotovo prispevalo dejstvo, da ga je enostavno implementirati, kakor tudi, da tvori
optimalne kode – simbolom, ki se pojavljajo najve�krat, dodeljuje najkrajše kode. V
prvem koraku moramo pregledati vhodno zaporedje in ugotoviti, kolikokrat se
posamezni simbol pojavlja (v literaturi obi�ajno navajamo verjetnosti posameznih
simbolov, v praksi pa zaradi hitrosti izvajanja rajši operiramo s frekvenco
pojavljanja, ki je celo število). Nato tabelo simbolov glede na število pojavljanj
uredimo v padajo�em vrstnem redu in vsak simbol predstavimo kot vozliš�e
drevesa. Sedaj lahko za�nemo graditi binarno drevo. Posebnost Huffmanovega
algoritma je, da gradi drevo od spodaj navzgor, t.j. od listov h korenu. Na vsakem
koraku izberemo dve vozliš�i VA in VB z najnižjo frekvenco pojavljanja. Ker je
tabela urejena padajo�e, nam vozliš� ni treba iskati, temve� vedno vzamemo
zadnji dve. Obe vozliš�i povežemo v novo delno drevo, katerega levi list je
vozliš�e VA, desni list vozliš�e VB, koren pa novo vozliš�e VAB. Frekvenco
pojavljanja novega vozliš�a VAB dobimo tako, da seštejemo frekvenci vozliš� VA in
VB. Nato vozliš�i VA in VB odstranimo iz seznama, vozliš�e VAB pa vstavimo tako,
da je seznam še vedno urejen padajo�e. Po vsakem koraku se seznam zmanjša
za en element. Postopek je kon�an, ko se število elementov v seznamu skr�i na
ena. Zadnji element predstavlja koren celotnega binarnega drevesa. Kode za
posamezni simbol dobimo tako, da obiš�emo vsa vozliš�a drevesa. Vsako
vozliš�e prispeva en bit v izhodni kodi simbola. Omenimo, da obstaja tudi razli�ica
Prakti�na uporaba algoritmov stiskanja podatkov 10
algoritma, kjer tabele simbolov ne urejamo po padajo�em vrstnem redu. V tem
primeru moramo na vsakem koraku pregledati celotno tabelo, da najdemo simbola
z najnižjo frekvenco pojavljanja. �eprav je iskanje bolj zamudno, pa odpade
vzdrževanje urejenosti tabele.
Primer: s Huffmanovim algoritmom kodirajmo stavek »Ra�unalnik ra�una …«. Najprej moramo
ugotoviti, kolikokrat se posamezni simbol pojavlja. Presledek je predstavljen s simbolom �.
VR1
Va4
V�
2
Vu2
Vn3
Vl1
Vi1
Vk1
V�
2
Vr1
Slika 2.3.1: Huffmanovo kodiranje (prvi korak)
Nato seznam uredimo padajo�e glede na frekvenco pojavljanja posameznega simbola. Primeren je
katerikoli algoritem, ki zna urediti seznam števil, npr. QuickSort.
VR1
Va4
V�
2
Vu2
Vn3
Vl1
Vi1
Vk1
V�
2
Vr1
Slika 2.3.2: Huffmanovo kodiranje (drugi korak)
Za�nemo graditi binarno drevo. Izberemo dva simbola z najmanjšo frekvenco pojavljanja: Vk in Vr
ter tvorimo novo vozliš�e Vkr s frekvenco 2 (seštejemo frekvenci simbolov Vk in Vr). Vozliš�i Vk in Vr
odstranimo iz seznama, vozliš�e Vkr pa vstavimo v seznam na šesto mesto tako, da je seznam še
vedno urejen padajo�e. Dejansko lahko vozliš�e Vkr uvrstimo poljubno na mesta 3, 4, 5 ali 6, pa se
optimalnost kode ne bi spremenila. Spremenile bi se samo kode posameznih simbolov.
VR1
Va4
V�
2
Vu2
Vn3
Vl1
Vi1
V�
2
Vk1
Vr1
Vkr2
Slika 2.3.3: Huffmanovo kodiranje (tretji korak)
V naslednjem koraku zopet izberemo dva simbola z najnižjo frekvenco pojavljanja: Vl in Vi. Tvorimo
Prakti�na uporaba algoritmov stiskanja podatkov 11
novo vozliš�e Vli, ki ima spet frekvenco 2. Simbola Vl in Vi odstranimo iz seznama, simbol Vli pa
vstavimo v seznam na sedmem mestu (ker mora biti seznam ves �as urejen padajo�e glede na
frekvenco pojavljanja).
VR1
Va4
V�
2
Vu2
Vn3
V�
2
Vk1
Vr1
Vkr2
Vl1
Vi1
Vli2
Slika 2.3.4: Huffmanovo kodiranje (�etrti korak)
Postopek ponavljamo in na vsakem koraku izberemo dve vozliš�i z najnižjo frekvenco, t.j. zadnji
dve vozliš�i v seznamu. Nadaljujemo z izbiro vozliš� Vli in VR in tvorimo novo vozliš�e VliR s
frekvenco 3. Vozliš�i Vli in VR odstranimo iz seznama, novo vozliš�e VliR uvrstimo v seznam na
tretjem mestu.
Va4
V�
2
Vu2
Vn3
V�
2
Vk1
Vr1
Vkr2
VR1
Vl1
Vi1
Vli2
VliR3
Slika 2.3.5: Huffmanovo kodiranje (peti korak)
Iz vozliš� V� in Vkr tvorimo vozliš�e V�kr. Vozliš�i V� in Vkr odstranimo iz seznama, novo vozliš�e
V�kr s frekvenco 4 pa vstavimo v seznam na drugem mestu.
Prakti�na uporaba algoritmov stiskanja podatkov 12
Va4
V�
2
Vu2
Vn3
VR1
Vl1
Vi1
Vli2
VliR3
V�
2
Vk1
Vr1
Vkr2
V�kr4
Slika 2.3.6: Huffmanovo kodiranje (šesti korak)
Vozliš�i V� in Vu nam data novo vozliš�e V�u s frekvenco 4, ki ga uvrstimo v seznam na tretjem
mestu.
Va4
Vn3
VR1
Vl1
Vi1
Vli2
VliR3
V�
2
Vk1
Vr1
Vkr2
V�kr4
V�
2
Vu2
V�u4
Slika 2.3.7: Huffmanovo kodiranje (sedmi korak)
Naslednji korak izbere vozliš�i Vn in VliR. Iz njih tvorimo vozliš�e VnliR s frekvenco 6, ki ga moramo
dati v seznam na prvo mesto.
Va4
V�
2
Vk1
Vr1
Vkr2
V�kr4
V�
2
Vu2
V�u4
Vn3
VR1
Vl1
Vi1
Vli2
VliR3
VnliR6
Slika 2.3.8: Huffmanovo kodiranje (osmi korak)
Prakti�na uporaba algoritmov stiskanja podatkov 13
V devetem koraku izberemo vozliš�i V�kr in V�u. Tvorimo novo vozliš�e V�kr�u s frekvenco 8, ki ga
moramo uvrstiti v seznam na prvo mesto.
Va4
Vn3
VR1
Vl1
Vi1
Vli2
VliR3
VnliR6
V�
2
Vk1
Vr1
Vkr2
V�kr4
V�
2
Vu2
V�u4
V�kr�u8
Slika 2.3.9: Huffmanovo kodiranje (deveti korak)
Ostaneta še dva koraka. V prvem izberemo vozliš�i VnliR in Va. Tvorimo novo vozliš�e VnliRa s
frekvenco 10, ki ga moramo dati v seznam na prvo mesto.
V�
2
Vk1
Vr1
Vkr2
V�kr4
V�
2
Vu2
V�u4
V�kr�u8
Va4
Vn3
VliR3
VR1
Vl1
Vi1
Vli2
VnliR6
VnliRa10
Slika 2.3.10: Huffmanovo kodiranje (deseti korak)
Na koncu sta nam ostali samo dve vozliš�i VnliRa in V�kr�u, ki ju združimo v vozliš�e VnliRa�kr�u s
frekvenco 18. Ker se je seznam skr�il na samo eno vozliš�e, je postopek kon�an, vozliš�e VnliRa�kr�u
pa predstavlja koren binarnega drevesa.
Prakti�na uporaba algoritmov stiskanja podatkov 14
V�
2
Vk1
Vr1
Vkr2
V�kr4
V�
2
Vu2
V�u4
V�kr�u8
Va4
Vn3
VliR3
VR1
Vl1
Vi1
Vli2
VnliR6
VnliRa10
VnliRa kr� �u18
Slika 2.3.11: Huffmanovo kodiranje (zadnji korak)
Da dobimo kode za naš nabor simbolov, moramo obiskati vsa vozliš�a drevesa. Prehod v vozliš�e
na levi ozna�imo z 0, prehod v vozliš�e na desni pa z 1. Tako vsako vozliš�e prispeva en bit v
kon�ni kodi simbola. Zapišimo Huffmanove kode za naše simbole:
Simbol Koda n 000 l 00100 i 00101 R 0011 a 01 � 100 k 1010 r 1011 � 110 u 111
Tabela 2.3.1: Huffmanove kode za primer »Ra�unalnik ra�una «
Iz primera lahko vidimo, da algoritem dodeljuje najkrajše kode ravno tistim
simbolom, ki se pojavljajo najve�krat. Pri gradnji drevesa bi lahko simbole izbirali
tudi kako druga�e. Dokler se držimo na�ela, da na vsakem koraku izberemo dva
simbola z najnižjo frekvenco pojavljanja, ne vplivamo na optimalnost kod, temve�
Prakti�na uporaba algoritmov stiskanja podatkov 15
kve�jemu na to, kakšno kodo bo dobil posamezni simbol. V praksi to dejstvo
predstavlja velik problem, saj obstaja ve� razli�nih enakovrednih dreves, iz katerih
dobimo optimalne Huffmanove kode. Ker optimalne kode niso enoli�ne, jih
dekodirnik ne more izra�unati. Zato moramo poleg kodiranih podatkov priložiti še
Huffmanovo drevo, iz katerega smo pridobili kode.
3 ALGORITEM DEFLATE
Kodirano zaporedje, ki ga tvori algoritem Deflate, se sestoji iz blokov poljubne
dolžine. Vsak blok kodiramo lo�eno. Pri tem uporabimo algoritme RLE, LZ77 in
Huffmanovo kodiranje v rahlo izboljšani obliki.
Prva izboljšava: vsako ujemanje, ki ga najdemo v slovarju, predstavimo z
dvoj�kom (dolžina ujemanja, odmik). Algoritem Deflate dovoljuje dolžino ujemanja
od najmanj tri do najve� dvestooseminpetdeset znakov. Simbole, ki jih ne najdemo
v slovarju oz. je njihova dolžina ujemanja manjša od treh znakov, zapišemo brez
kodiranja kot literale direktno v izhodni niz. Njihove vrednosti ležijo v intervalu
[0..255]. Odmik je lahko podan z najve� petnajstimi biti, zato je velikost slovarja
omejena na 32 kB (215=32768).
Druga izboljšava: posebnost algoritma Deflate je tudi, kako poskuša najti
najdaljše ujemanje v slovarju. Ni� ga ne moti, �e se ujemanje nadaljuje preko
zadnjega znaka slovarja, t.j. v vhodno zaporedje, ki ga moramo šele obdelati.
Uporaba te izboljšave ni obvezna.
Primer: imejmo stavek »Ra�unalnik ra�una, ra�una, ra�una!« in slovar naj obsega besedi
»Ra�unalnik ra�una,«.
Prakti�na uporaba algoritmov stiskanja podatkov 16
slovar besedilo
r a � u n a , r a � u n a !r a � u n a ,...
Slika 3.1: Algoritem Deflate (izboljšano iskanje v slovarju)
Obdelujemo presledek. Ujemanje najdemo na odmiku 8. Po vrsti beremo znake vhodnega
zaporedja, ki so vsi v slovarju, dokler ne pridemo do naslednjega presledka. Ker smo slovar
iz�rpali, bi po izvornem algoritmu LZ77 zaklju�ili in v izhodno zaporedje zapisali (8,8, ). Algoritem
Deflate pa spretno izkoriš�a ponavljanje in nadaljuje s primerjanjem vse dokler najde ujemanje.
Tako v izhodno zaporedje zapiše (15,8) in za�ne z novim iskanjem za znak »!«. Spomnimo, da ima
dvoj�ek pri algoritmu Deflate na prvem mestu dolžino ujemanja, na drugem pa odmik.
Tretja izboljšava: ki jo uporablja algoritem Deflate, je sekundarno iskanje. Najprej
po že opisanem postopku dolo�imo najdaljše ujemanje. Nato shranimo prvo �rko
pravkar obdelane besede in poskušamo najti daljše ujemanje za preostanek. �e
nam uspe, v izhodni niz shranimo prvo �rko kot literal, nato pa še dvoj�ek za
sekundarno ujemanje. V nasprotnem primeru shranimo dvoj�ek za prvotno
ujemanje. Uporaba te izboljšave ni obvezna.
�etrta izboljšava: ko gradimo Huffmanovo drevo, ne moremo vplivati, kje v
drevesu se bo posamezni simbol pojavil. Tako lahko imamo dolge in kratke kode
pomešane, dolge kode lahko nastopajo na levi strani drevesa, kratke na desni itd.
Algoritem Deflate zahteva, da so kode urejene po dolžini od leve proti desni, kode
enakih dolžin pa morajo biti urejene po simbolih, ki jih predstavljajo. Kode, ki jih
dobimo iz takšnega drevesa, imenujemo kanoni�ne Huffmanove kode in imajo
lepo lastnost, da jih lahko predstavimo kot zaporedje dolžin. V splošnem
Huffmanovo drevo ni urejeno, zato ga moramo najprej pretvoriti v kanoni�no
obliko. Pri tem si lahko pomagamo s preprostim algoritmom, ki ga je napisal P.
Deutsch [2]. Ideja je zelo u�inkovita. Namesto, da urejamo drevo, rajši
posameznim simbolom dodelimo nove kode, ki pa morajo biti enake dolžine kot
prej. Sledi algoritem:
Prakti�na uporaba algoritmov stiskanja podatkov 17
1. Vse simbole imamo v tabeli Simbol[255]
2. Ugotovimo najdaljšo dolžino kode: MAXBITS
3. Preštejemo število simbolov za vsako dolžino in rezultat shranimo v tabelo Count[MAXBITS]
for (int n = 0; n <= 255; n++)
Count[dolžina kode za n-ti simbol]++
4. Za vsako dolžino poiš�emo za�etno kodo in jo shranimo v tabelo NextCode[MAXBITS]
Code = 0
Count[0] = 0
for (int bits = 1; bits <= MAXBITS; bits++)
{
Code = (Code + Count[bits - 1]) << 1
NextCode[bits] = Code
}
5. Posameznim simbolom dodelimo nove (zaporedne) kode
for (int n = 0; n <= 255; n++)
{
int len=dolžina kode za n-ti simbol
if (len != 0)
{
Simbol[n] = NextCode[len]
NextCode[len]++
}
}
Primer: Huffmanove kode iz tabele 2.3.1 pretvorimo v kanoni�ne Huffmanove kode z uporabo
zgoraj opisanega algoritma. Najprej kode predstavimo z zaporedjem njihovih dolžin: (n=3, l=5, i=5,
R=4, a=2, �=3, k=4, r=4, �=3, u=3). Vidimo, da je najdaljša dolžina kode 5 bitov: MAXBITS=5.
Tvorimo tabelo Count[5]:
Dolžina kode Število simbolov 0 0 1 0 2 1 3 4 4 3 5 2
Tabela 3.1: Tabela Count[5] - število kod glede na njihovo dolžino
Prakti�na uporaba algoritmov stiskanja podatkov 18
Sedaj za vsako dolžino poiš�emo za�etno kodo in jo shranimo v tabelo NextCode[5]. Spomnimo,
da operacija << 1 pomeni množenje z 2 (pomik bitov za eno mesto v levo). Ker nimamo nobene
kode z dolžino 1, je NextCode[1]=0: Code = (0 + Count[0]) << 1 = 0. Imamo eno kodo z dolžino 2 in
NextCode[2]=0: Code = (0 + Count[1]) << 1 = 0. Imamo štiri kode z dolžino 3 in NextCode[3]=2:
Code = (0 + Count[2]) << 1 = 2. Imamo tri kode z dolžino 4 in NextCode[4]=12: Code = (2 +
Count[3]) << 1 = 12. In kon�no imamo dve kodi z dolžino 5 in NextCode[5]=30: Code = (12 +
Count[4]) << 1 = 30. Kon�na tabela izgleda takole:
Dolžina kode NextCode[ ] 0 0 1 0 2 0 3 2 4 12 5 30
Tabela 3.2: Tabela NextCode[5] z za�etnimi kodami za posamezne dolžine
V zadnjem koraku generiramo nove kode. Simboli, ki ne nastopajo v vhodnem zaporedju, nimajo
kode (dolžino kode je 0), zato jih presko�imo. Zaradi pogoja, da morajo biti kode enake dolžine
urejene po simbolih, ki jih predstavljajo, je vrstni red dodeljevanja kod pomemben. Pravilni vrstni
red zagotovimo, �e tabelo simbolov obdelamo po ordinalnem vrstnem redu. Znaki z veljavno kodo
so: �, R, a, i, k, l, n, r, u in �. Prvi je znak �, dolžina njegove kode pa je 3 (glej tabelo 2.3.1). Iz
NextCode[3] dobimo njegovo novo kodo: 2 (0102). NextCode[3] pove�amo za ena: NextCode[3]=3.
Podobno obdelamo vse ostale simbole:
Simbol Koda NextCode[ ] Nova koda Novi NextCode[ ] � 100 NextCode[3]=2 010 NextCode[3]=3 R 0011 NextCode[4]=12 1100 NextCode[4]=13 a 01 NextCode[2]=0 00 NextCode[2]=1 i 00101 NextCode[5]=30 11110 NextCode[5]=31 k 1010 NextCode[4]=13 1101 NextCode[4]=14 l 00100 NextCode[5]=31 11111 NextCode[5]=32 n 000 NextCode[3]=3 011 NextCode[3]=4 r 1011 NextCode[4]=14 1110 NextCode[4]=15 u 111 NextCode[3]=4 100 NextCode[3]=5 � 110 NextCode[3]=5 101 NextCode[3]=6
Tabela 3.3: Kanoni�ne Huffmanove kode
Prakti�na uporaba algoritmov stiskanja podatkov 19
Celotno drevo lahko zapišemo kot zaporedje dolžin: (3,4,2,5,4,5,3,4,3,3) in vsak dekodirnik lahko
dejanske kode izra�una po zgoraj opisanem algoritmu. Za pravilno predstavitev bi morali zaporedje
zapisati z dvestošestinpetdesetimi dolžinami, kajti iz zgornjega zapisa lahko dekodirnik dolo�i kode
za posamezni simbol, ne pa tudi kateremu simbolu koda pripada. Pravilen zapis bi bil: (0, 0, 0, 0
…, 3, 0,0, …, 4, 0, 0, 0, …, 2, 0, 0, 0, … itd).
V praksi algoritem deluje s celotnim naborom znakov z ordinalnimi vrednostmi
od 0 do 255, ki pa po navadi ne nastopajo vsi pri kodiranju bloka. Tako ima
zaporedje dolžin veliko zaporednih ni�el. Tudi simboli, ki so bili uporabljeni pri
kodiranju, imajo zelo pogosto kode enakih dolžin. To pa so lastnosti, ki kar kli�ejo
po uporabi algoritma RLE.
3.1 Na�ini kodiranja
Algoritem Deflate kodira podatke v blokih. Dolžina bloka in število blokov sta
poljubna, obi�ajno pa vsako datoteko kodiramo v svojem bloku. Prvi zlog bloka
ima naslednji pomen:
• BFINAL (prvi bit): je 1 za zadnji blok v nizu in 0 za vse ostale bloke.
• BTYPE (naslednja dva bita): ozna�ujeta vrsto kodiranja. Lahko imata
vrednosti: 00-nekodirano, 01-kodirano s fiksnimi (vnaprej definiranimi)
kodnimi tabelami in 10-kodirano z dinami�nimi kodnimi tabelami.
Nekodirano (BTYPE=00): prvi zlog bloka se za�ne z 000 ali 100. Preostali biti
niso pomembni. Nato sledi dolžina bloka v zlogih (LEN) in eniški komplement
istega podatka (NLEN). Obe števili sta nepredzna�eni 16-bitni števili, zato je
dolžina bloka omejena na 64 kB (216=65535). Sledijo nekodirani podatki.
Kodirano z vnaprej definiranimi kodnimi tabelami (BTYPE=01): prvi zlog bloka
se za�ne z 001 ali 101. Simbol v kodiranem bloku je lahko: nekodiran znak oz.
literal (vrednosti iz intervala [0..255]) ali pa dvoj�ek (dolžina ujemanja, odmik), kjer
je dolžina ujemanja iz intervala [3..258] in odmik iz intervala [1..32768]. Literale in
dolžine ujemanja združimo v eno kodno tabelo z vrednostmi iz intervala [0..287].
Prakti�na uporaba algoritmov stiskanja podatkov 20
Vrednosti iz intervala [0..255] pripadajo literalom, vrednost 256 predstavlja konec
bloka, vrednosti [257..287] pa predstavljajo dolžine ujemanja. Ker se kodi 286 in
287 ne smeta uporabljati (sta rezervirani), dobimo uporaben interval v razponu
[0..285]. Slednjih devetindvajset kod iz intervala [257..285] je premalo, da bi lahko
enoli�no kodirali dvestošestinpetdeset dolžin ujemanja iz intervala [3..258], zato
jim dodamo dodatne bite kot prikazuje tabela 3.1.1. Tabela 3.1.2 prikazuje
Huffmanove kode za literale/dolžine ujemanja, ki jih zapisujemo v izhodni kodirani
blok.
Koda Dodatni biti
Dolžina Koda Dodatni biti
Dolžina Koda Dodatni biti
Dolžina
257 0 3 267 1 15-16 277 4 67-82 258 0 4 268 1 17-18 278 4 83-98 259 0 5 269 2 19-22 279 4 99-114 260 0 6 270 2 23-26 280 4 115-130 261 0 7 271 2 27-30 281 5 131-162 262 0 8 272 2 31-33 282 5 163-194 263 0 9 273 3 35-42 283 5 195-226 264 0 10 274 3 43-50 284 5 227-257 265 1 11-12 275 3 51-58 285 0 258 266 1 13-14 276 3 59-66
Tabela 3.1.1: Kodna tabela za dolžine ujemanja
Koda Dolžina Huffmanova koda 0-143 8 00110000-10111111
144-255 9 110010000-111111111 256-279 7 0000000-0010111 280-287 8 11000000-11000111
Tabela 3.1.2: Huffmanove kode za literale/dolžine ujemanja
Primer: kako z uporabo zgornjih tabel kodiramo dolžine ujemanja? (A) �e je algoritem LZ77 v
slovarju našel niz dolžine štirih znakov, ji pripada koda 258 (glej tabelo 3.1.1), Huffmanova koda za
258 pa se glasi 0000010 (glej tabelo 3.1.2). To kodo zapišemo v izhodni kodirani blok. (B) �e
najdemo ujemanje dolžine dvanajstih znakov, ji pripada koda 265, ustrezna Huffmanova koda pa je
0001001. Da lo�imo med dolžinama enajst in dvanajst znakov (obema pripada koda 265), moramo
dodati še en bit: za dolžino enajst je ta bit 0, za dolžino dvanajst pa 1. Cela koda se tako glasi:
0001001{1}. Dodatni bit je v oklepajih zaradi lepšega prikaza. (C) Za ujemanje dolžine
Prakti�na uporaba algoritmov stiskanja podatkov 21
štiriindvajsetih znakov dobimo kodo 270, Huffmanova koda je: 0001110{01}. (D) Za dolžino
dvestošestinpetdeset dobimo kodo 284, Huffmanova koda pa se glasi: 11000100{11101}. (E) Kodo
256, ki ozna�uje konec bloka, zapišemo kot 0000000.
Za kodiranje odmikov potrebujemo drugo tabelo s kodami iz intervala [0..31].
Kodi 30 in 31 se ne smeta uporabljati (sta rezervirani). Tako dobimo trideset
uporabnih kod, ki jih lahko predstavimo s petimi biti. Ker pa je lahko odmik v
intervalu [1..32768], potrebujemo za njegovo enoli�no kodiranje dodatne bite.
Kode so prikazane v tabeli 3.1.3.
Koda Dodatni biti
Odmik Koda Dodatni biti
Odmik Koda Dodatni biti
Odmik
0 0 1 10 4 33-48 20 9 1025-1536 1 0 2 11 4 49-64 21 9 1537-2048 2 0 3 12 5 65-96 22 10 2049-3072 3 0 4 13 5 97-128 23 10 3073-4096 4 1 5-6 14 6 129-192 24 11 4097-6144 5 1 7-8 15 6 193-256 25 11 6146-8192 6 2 9-12 16 7 257-384 26 12 8193-12288 7 2 13-16 17 7 385-512 27 12 12289-16384 8 3 17-24 18 8 513-768 28 13 16385-24576 9 3 25-32 19 8 769-1024 29 13 24577-32768
Tabela 3.1.3: Huffmanove kode za odmike
Primer: kako z uporabo zgornje tabele kodiramo odmike? (A) Iz tabele je razvidno, da odmiku 5
pripada koda 4 z enim dodatnim bitom: 00100{0}. Odmik 6 bi kodirali kot 00100{1}. (B) Odmiku 180
pripada koda 14 s šestimi dodatnimi biti: 01110{110011}. Koda za odmik 180 je enainpetdeseta
koda iz intervala [129..192], zato: 51 = 3316 = 1100112. (C) Odmiku 8195 pripada koda 26 z
dvanajstimi dodatnimi biti: 11010{000000000010}.
Primer: uporabimo algoritem Deflate z vnaprej definiranimi kodnimi tabelami nad nizom
“Ra�unalnik ra�una”. Algoritem LZ77 nam da zaporedje: Ra�unalnik r(5,11). ASCII kode za literale
so: R=82 (5216), a=97 (6116), �=232 (E816), u=117 (7516), n=110 (6E16), a=97 (6116), l=108 (6C16),
n=110 (6E16), i=105 (6916), k=107 (6B16), �=32 (2016) in r=114 (7216). To zaporedje sedaj
kodirajmo. Ker bomo imeli samo en blok, se trije kontrolni biti bloka glasijo: 101. Znak R ima ASCII
kodo 82 (5216), zato spada v interval kod [0..143], ki se za�nejo pri 00110000 (3016). �e seštejemo
3016 in 5216, dobimo kodo: 8216, zato v kodirani blok zapišemo: 10000010. Za znak a dobimo: 3016
+ 6116 = 9116 in v kodirani blok zapišemo: 10010001. Znak � ima kodo 232 (E816), zato spada v
Prakti�na uporaba algoritmov stiskanja podatkov 22
interval kod [144..255], ki se za�nejo pri 110010000 (19016). Koda 232 je oseminosemdeseta koda
v tem zaporedju: 232-114=88 (5816). �e seštejemo 19016 + 5816, dobimo kodo 1E816 in v kodirani
blok zapišemo: 111101000. Po istem postopku kodiramo tudi vse ostale literale: u=10101001
n=10011110 a=10010001 l=10011100 n=10011110 i=10011001 k=10011011 �=10010000
r=10100010. Kodirati moramo še dvoj�ek (5,11). Dolžina 5 nam da kodo 259, ki jo kodiramo s
sedmimi biti: 0000011 (glej tabeli 3.1.1 in 3.1.2). Odmik kodiramo s pomo�jo tabele 3.1.3. Za odmik
11 dobimo kodo 6, potrebujemo pa še dva dodatna bita. Dobimo: 00110{10}. Na konec bloka
moramo dodati še kodo 256: 0000000. Celoten kodirani blok se glasi: 101 10000010 10010001
111101000 10101001 10011110 10010001 10011100 10011110 10011001 10011011 10010000
10100010 0000011 0011010 0000000.
Obe kodni tabeli sta vgrajeni v kodirnik in dekodirnik, zato ju ni potrebno
prilagati h kodiranemu bloku. Kodirani podatki sledijo takoj za tremi kontrolnimi biti
prvega zloga. Blok se zaklju�i s Huffmanovo kodo za simbol 256: 00000002.
Kodirano z dinami�nimi kodnimi tabelami (BTYPE=10): prvi zlog bloka se
za�ne z 010 ali 110. Sledijo opisi kodnih tabel:
• Število kod v tabeli literalov/dolžin (HLIT): pet bitov. Literali lahko
zavzamejo vrednosti iz intervala [0..255], vrednost 256 predstavlja konec
bloka, vrednosti iz intervala [257..285] pa predstavljajo dolžine (glej
tabelo 3.1.1). Nekatere dolžine lahko manjkajo, zato HLIT pove, katera
koda dolžine je zadnja uporabljena (npr. �e je zadnja uporabljena koda
dolžine enaka 259, je HLIT enak 2: 259 - 257 = 2).
• Število kod v tabeli odmikov (HDIST): pet bitov. V tabeli je trideset kod
(glej tabelo 3.1.3), ker pa nekatere kode lahko manjkajo, HDIST pove,
kateri odmik je zadnji uporabljen (npr. �e je zadnji uporabljeni odmik s
kodo 6, je HDIST enak 6).
• Število kod v tabeli (HCLEN), s katerimi sta kodirani tabeli literalov/dolžin
in odmikov: štirje biti. Vrednosti so lahko iz intervala [0..15], pomenijo pa
kode iz intervala [4..19]. Ker nekatere kode lahko manjkajo, (HCLEN +
4) pove, koliko kod je v tabeli.
• Zaporedje dolžin (HCLIST) za kode, s katerimi sta kodirani tabeli
literalov/dolžin in odmikov. Spomnimo, da namesto kod v kanoni�ni
Prakti�na uporaba algoritmov stiskanja podatkov 23
obliki lahko pišemo zaporedje dolžin, iz katerega lahko rekonstruiramo
kodno tabelo. Vseh dolžin je (HCLEN+4), vsaka je dolžine treh bitov.
• Zaporedje dolžin (HLITLIST) za kode iz tabele literalov/dolžin. Vseh
dolžin je (257+HLIT) in so kodirane po postopku, opisanem v poglavju
3.2.
• Zaporedje dolžin (HDISTLIST) za kode iz tabele odmikov. Vseh dolžin je
(HDIST+1) in so kodirane po postopku, opisanem v poglavju 3.2.
• Sledijo kodirani podatki: podatki so kodirani s pomo�jo obeh kodnih tabel
za literale/dolžine in odmike.
• Koda za konec bloka: Huffmanova koda za simbol 256.
3.2 Dinami�ne kodne tabele
Kodirnik med postopkom kodiranja sam generira dve kodni tabeli, eno za
literale/dolžine ujemanja in drugo za odmike. Tabeli dobimo iz Huffmanovih
dreves. Kakšno bo drevo, je povsem odvisno od algoritma. Bolj izpopolnjen
algoritem lahko zbere boljšo statistiko in tako generira krajši izhodni niz. Slabši
algoritem se bo morda zadovoljil s krajšim ujemanjem, a bo kodiranje hitrejše. Pri
izbiri algoritma moramo tako vedno delati kompromis med hitrostjo kodiranja in
velikostjo kodiranega niza. Ker se tabeli tvorita dinami�no glede na vhodne
podatke, ju moramo priložiti k vsakemu kodiranemu bloku. Algoritem Deflate kodni
tabeli zapiše v zelo strnjeni obliki. V grobem je postopek za zapis kodnih tabel
slede�i:
• Za vsako od obeh tabel (tabela literalov/dolžin in tabela odmikov)
zgradimo Huffmanovo drevo.
• Obe Huffmanovi drevesi pretvorimo v kanoni�no obliko.
• Kanoni�ne kode zapišemo kot zaporedje dolžin. Vsako drevo ima svoje
zaporedje dolžin: SLIT in SDIST,
• Obe zaporedji dolžin združimo v eno zaporedje S = SLIT + SDIST, pri
�emer ni�le s konca posameznega zaporedja odstranimo.
• Novo zaporedje S kodiramo z algoritmom RLE, da dobimo še krajše
Prakti�na uporaba algoritmov stiskanja podatkov 24
zaporedje SRLE.
• Iz krajšega zaporedja SRLE zgradimo novo Huffmanovo drevo.
• Novo Huffmanovo drevo pretvorimo v kanoni�no obliko.
• Kode iz tako dobljenega drevesa predstavimo z zaporedjem dolžin.
Zapišemo dolžine za vse kode [0..18], neuporabljene kode inicializiramo
na 0.
• Zaporedje premešamo. Vrstni red je predpisan in sicer si kode sledijo v
tem zaporedju: 16 17 18 0 8 7 9 6 10 5 11 4 12 3 13 2 14 1
15.
• Odstranimo ni�le s konca zaporedja, preostanek pa zapišemo v glavo
kodiranega bloka (HCLIST).
• Zaporedje SRLE kodiramo s prej pridobljenimi kanoni�nimi Huffmanovimi
kodami. Zaporedje zapišemo v glavo kodiranega bloka takoj za
zaporedjem (HCLIST) in predstavlja kodirani tabeli za literale/dolžine
(HLITLIST) in odmike (HDISTLIST).
Postopek kodiranja z algoritmom RLE: kako pridemo do Huffmanovih kod, smo
opisali v poglavju 2.3. Tudi pretvorbo Huffmanovih kod v kanoni�ne Huffmanove
kode smo že opisali v poglavju 3 (�etrta izboljšava). Zato na tem mestu
predpostavimo, da zaporedje dolžin že imamo. Dolžine v tem zaporedju se
obi�ajno ponavljajo, zato jih lahko dobro stisnemo z uporabo algoritma RLE, da
dobimo še krajše zaporedje. Algoritem Deflate iz vhodnega zaporedja dolžin tvori
novo zaporedje in sicer na naslednji na�in:
• �e se dolžina ponovi trikrat ali manj, jo prepišemo v novo zaporedje.
• �e se dolžina ponovi ve� kot trikrat, jo kodiramo z uporabo algoritma
RLE. V novo zaporedje zapišemo dolžino, ki ji sledi koda 16 in število
ponovitev (kolikokrat se dolžina ponovi). Število ponovitev je dolžine
dveh bitov in ozna�uje od tri do šest ponovitev (002 predstavlja tri
ponovitve, 112 predstavlja šest ponovitev).
• Izkušnje kažejo, da se dolžina ni� pojavlja zelo pogosto, zato ima dve
posebni kodi. Prva posebna koda je 17, ki ji sledi 3-bitno število, ki
Prakti�na uporaba algoritmov stiskanja podatkov 25
pomeni od tri do deset ponovitev (0002 predstavlja tri ponovitve, 1112
predstavlja deset ponovitev). Druga posebna koda je 18, ki ji sledi 7-
bitno število, ki pomeni od enajst do stoosemintrideset ponovitev
(00000002 predstavlja enajst ponovitev, 11111112 predstavlja
stoosemintrideset ponovitev).
Primer: uporabe algoritma RLE. (A) Kako kodiramo šest zaporednih sedmic: 7, 7, 7, 7, 7, 7?
Zapišemo: 7 16 102 (002 so tri ponovitve, 012 so štriri ponovitve, 102 je pet ponovitev in 112 je šest
ponovitev). Torej, prva sedmica in pet ponovitev, nam da šest zaporednih sedmic. (B) Kako
kodiramo enajst zaporednih štiric: 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4? Pišemo: 4 16 112 16 012. (C) Kako
kodiramo deset zaporednih ni�el? Pišemo: 17 1112. (D) Kako kodiramo dvajset zaporednih ni�el?
Pišemo: 18 00010012 (koda 20 je deveta koda iz intervala [11..138]).
Primer: stavek »Ra�unalnik ra�una« kodirajmo z dinami�nimi kodnimi tabelami.
(1) Algoritem LZ77 nam da naslednje zaporedje: R, a, �, u, n, a, l, n, i, k, �, r, (5,11). Abeceda
literalov/dolžin vsebuje simbole z ordinalnimi vrednostmi iz intervala [0..287]. Spomnimo, da kod
286 in 287 ne smemo uporabljati, vendar morata vseeno sodelovati pri gradnji Huffmanovega
drevesa. Dolžina 5 nam da kodo 259 (glej tabelo 3.1.1), ki jo bomo predstavili s simbolom d259.
Simbol za konec bloka bomo ozna�ili z EOB. Z uporabo Huffmanovega kodiranja dobimo enega
izmed naborov Huffmanovih kod:
Simbol Ord. vred. Huffmanova koda Kanoni�na Huffmanova koda � 32 0100 0110 R 82 0010 0111 a 97 11 00 i 105 0110 1000 k 107 0111 1001 l 108 0001 1010 n 110 100 010 r 114 0101 1011 u 117 0000 1100 � 232 0011 1101 EOB 256 1010 1110 d259 259 1011 1111
Tabela 3.2.1: Huffmanove kode in kanoni�ne Huffmanove kode za literale/dolžine
Zaporedje dolžin, s katerim predstavimo kanoni�ne Huffmanove kode, se glasi: 0{32}, 4, 0{49}, 4,
0{14}, 2, 0{7}, 4, 0, 4, 4, 0, 3, 0, 0, 0, 4, 0, 0, 4, 0{114}, 4, 0{23}, 4, 0, 0, 4, 0{28}. Da je zaporedje
Prakti�na uporaba algoritmov stiskanja podatkov 26
bolj pregledno, smo ponovitve ni�el zapisali v zavitih oklepajih.
(2) Podobno moramo storiti tudi za odmike. V našem primeru imamo samo en odmik: 11, kar nam
da kodo 6 (glej tabelo 3.1.3) z dvema dodatnima bitoma: 102. Huffmanovo drevo je trivialno, z enim
samim vozliš�em, ki mu priredimo kodo 0. �e bi imeli ve� odmikov, bi s pomo�jo tabele 3.1.3 in
Huffmanovega kodiranja za vsak odmik dolo�ili kanoni�no Huffmanovo kodo. Ustrezno zaporedje
dolžin se glasi: 0{6}, 1, 0{25}. �eprav kod 30 in 31 ne smemo uporabljati, morata vseeno sodelovati
pri gradnji Huffmanovega drevesa, zato ima zaporedje dvaintrideset elementov.
(3) Oba zaporedja dolžin združimo v eno zaporedje, kjer lahko ponavljajo�e se ni�le na koncu
posameznega zaporedja izpustimo. Dobimo: 0{32}, 4, 0{49}, 4, 0{14}, 2, 0{7}, 4, 0, 4, 4, 0, 3, 0, 0,
0, 4, 0, 0, 4, 0{114}, 4, 0{23}, 4, 0, 0, 4, 0{6}, 1. Dobljeno zaporedje kodiramo z algoritmom RLE: 18
00101012 4 18 01001102 4 18 00000112 2 17 1002 4 0 4 4 0 3 17 0002 4 0 0 4 18 11001112 4 18
00011002 4 0 0 4 17 0112 1.
(4) Za novo zaporedje generiramo Huffmanove kode. V abecedi za Huffmanovo drevo sodelujejo
samo simboli iz intervala [0..18], bitne vrednosti so dopolnilo h kodam in jih ne kodiramo. Imamo
simbole: 18, 4, 18, 4, 18, 2, 17, 4, 0, 4, 4, 0, 3, 17, 4, 0, 0, 4, 18, 4, 18, 4, 0, 0, 4, 17 in 1. Pri
Huffmanovem kodiranju potrebujemo tudi njihove frekvence, zato zapišimo še te: 0{6}, 1{1}, 2{1},
3{1}, 4{10}, 17{3} in 18{5}.
Simbol Huffmanova koda Kanoni�na Huffmanova koda 0 01 00 1 1011 1110 2 10100 11110 3 10101 11111 4 00 01 17 100 110 18 11 10
Tabela 3.2.2: Huffmanove kode in kanoni�ne Huffmanove kode za zaporedje RLE
(5) Zapišimo zaporedje dolžin za vse simbole [0..18]:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 2 4 5 5 2 0 0 0 0 0 0 0 0 0 0 0 0 3 2
in ga premešajmo v skladu s predpisom:
Prakti�na uporaba algoritmov stiskanja podatkov 27
16 17 18 0 8 7 9 6 10 5 11 4 12 3 13 2 14 1 15 0 3 2 2 0 0 0 0 0 0 0 2 0 5 0 5 0 4 0
(6) Odstranimo ni�le s konca zaporedja: v našem primeru imamo na koncu samo eno ni�lo, zato v
kodirani blok zapišemo zaporedje prvih osemnajstih števil. To je naše zaporedje HCLIST, ki ga
zapišemo v glavo kodiranega bloka: 0 3 2 2 0 0 0 0 0 0 0 2 0 5 0 5 0 4.
Primer: za prejšnji primer zapišimo celotno glavo bloka:
(1) Trije biti na za�etku bloka: 110.
(2) Pet bitov za HLIT: 2 (000102). Zadnji uporabljeni simbol v tabeli literalov/dolžin je simbol
259 (259 - 257 = 2).
(3) Pet bitov za HDIST: 6 (001102). Zadnji uporabljeni simbol iz tabele odmikov je 6.
(4) Štirje biti za HCLEN: 14 (11102). Pomenijo, da imamo 18 kod (HCLEN+4).
(5) Zaporedje dolžin HCLIST. V prejšnjem primeru smo dobili: 0 3 2 2 0 0 0 0 0 0 0 2 0 5 0 5 0
4. Vsako dolžino zapišemo kot 3-bitno število: 000 011 010 010 000 000 000 000 000
000 000 010 000 101 000 101 000 100.
(6) Zaporedje, kodirano z algoritmom RLE, kodiramo še s kanoni�nimi Huffmanovimi kodami:
18 00101012 4 18 01001102 4 18 00000112 2 17 1002 4 0 4 4 0 3 17 0002 4 0 0 4 18
11001112 4 18 00011002 4 0 0 4 17 0112 1 102. Dobimo: 10 0010101 01 10 0100110 01 10
0000011 11110 110 100 01 00 01 01 00 11111 110 000 01 00 00 01 10 1100111 01 10
0001100 01 00 00 01 110 011 1110 10. To zaporedje nam predstavlja obe kodni tabeli za
literale/dolžine (HLITLIST) in odmike (HDISTLIST).
(7) Sledijo podatki, kodirani s pomo�jo obeh kodnih tabel: R=01112, a=002, �=11012, u=11002,
n=0102, a=002, l=10102, n=0102, i=10002, k=10012, �=01102, r=10112, dolžina
5=d259=11112, odmik 11=0 102.
(8) Konec bloka: koda za simbol 256=11102.
Ker je postopek kodiranja bitno naravnan, povejmo še, kako moramo
združevati bite, da bodo podatki pravilno predstavljeni. Vsa števila so
predstavljena v obliki: b7 b6 b5 b4 b3 b2 b1 b0, kjer je najmanj pomemben bit b0
na desni in najbolj pomemben bit b7 na levi. Bite polnimo po vrsti od b0 do b7:
• Vse vrednosti, ki niso Huffmanove kode, zapišemo po bitih od najmanj
pomembnega proti najbolj pomembnemu bitu.
• Huffmanove kode podajamo v obratnem vrstnem redu, t.j. bite
Prakti�na uporaba algoritmov stiskanja podatkov 28
zapisujemo od najbolj pomembnega proti najmanj pomembnemu bitu.
Primer: blok, kodiran z dinami�nimi kodnimi tabelami, mora imeti na za�etku oznako 102. Sledi mu
5-bitno število uporabljenih kod v tabeli literalov/dolžin, HLIT. Recimo, da je HLIT=7. Tedaj prvi zlog
bloka zapišemo: 00111 10 1 (b0=1, b1=0, b2=1, b3=1, b4=1, b5=1, b6=0 in b7=0). Huffmanovo
kodo 10112 moramo zapisati v obratnem vrstenm redu: 11012 (b0=1, b1=0, b2=1, b3=1 itd).
4 STRUKTURA DATOTEKE ZIP
Datoteke ZIP so namenjene arhiviranju in izmenjevanju podatkov. Za
specifikacijo [5] skrbi podjetje PKWare Inc., katerega ustanovitelj je bil P. W. Katz
(1962 – 2000), ki je med drugim tudi avtor algoritma Deflate.
Mi se bomo omejili na osnovno zgradbo datoteke ZIP, ki bo omogo�ala zgolj
arhiviranje in branje arhivskih datotek. Izpustili pa bomo razli�ne možnosti
kodiranja ZIP datotek, uporabo certifikatov in kreiranje velikih Zip64™ arhivov, ki
dovoljujejo arhiviranje datotek, ve�jih od 4 GB.
Ni nujno, da se arhiv ZIP nahaja v eni datoteki ZIP. Lahko ga razbijemo na ve�
delov poljubne dolžine, npr. za prenos podatkov z disketo. Poznamo dve vrsti
segmentiranja. Kadar arhiv delimo na ve� disket, je ime arhiva na vseh disketah
enako, npr. Podatki20080901.ZIP. Številko segmenta razberemo iz oznake
diskete (angl. volume label) in mora biti v obliki PKBACK#nnn, kjer nnn predstavlja
številko segmenta. Pri delitvi na disk moramo upoštevati, da v mapi ne moreta
obstajati dve datoteki z enakim imenom. Zato ima samo zadnja datoteka
(segment) kon�nico ZIP, vse prejšnje pa imajo številko segmenta v imenu.
Primer: �e datoteko Podatki20080901.ZIP razbijemo na tri segmente v isto mapo, morajo biti
ustrezna imena datotek: Podatki20080901.Z01, Podatki20080901.Z02 in Podatki20080901.ZIP.
Datoteke, ki jih dodamo v arhiv ZIP, so lahko shranjene v poljubnem vrstnem
redu. Celotna zgradba datoteke ZIP je naslednja (elementi, ki so obarvani sivo, za
Prakti�na uporaba algoritmov stiskanja podatkov 29
našo aplikacijo niso potrebni in jih ne bomo opisovali. Celoten opis lahko bralec
najde v [5]):
• (A) prva datoteka: opis (local file header 1)
• (B) prva datoteka: kodirani podatki (file data 1)
• (C) [prva datoteka: dodatni opis (data descriptor 1)]
• …
• (A) N-ta datoteka: opis (local file header N)
• (B) N-ta datoteka: kodirani podatki (file data N)
• (C) [N-ta datoteka: dodatni opis (data descriptor N)]
• (D) [Podatki za dekodiranje (archive decryption header)]
• (E) [Dodatni podatki (archive extra data record)]
• (F) Katalog (central directory)
• (G) [Konec ZIP64 kataloga (ZIP64 end of central directory record)]
• (H) [Konec ZIP64 lokatorja (ZIP64 end of central directory locator)]
• (I) Konec kataloga (end of central directory)
(A) Opis datoteke (local file header): pred vsako kodirano datoteko moramo
zapisati blok z osnovnimi podatki o datoteki. �eprav so ti podatki na voljo tudi v
katalogu na koncu datoteke ZIP, jih moramo navajati tudi pred kodiranimi podatki
in sicer zaradi naprav, ki ne omogo�ajo naklju�nega iskanja.
A.1: ID bloka (local file header signature) 4 zlogi
Mora biti 04035b5016
A.2: Minimalna verzija za dearhiviranje (version needed to extract) 2 zloga
1.0: privzeto
1.1: datoteka predstavlja disk
2.0: datoteka predstavlja mapo
2.0: datoteka je stisnjena z algoritmom Deflate
2.0: datoteka je zaš�itena (kodirana) z osnovnim algoritmom PKWARE
2.1: datoteka je stisnjena z algoritmom Deflate64
2.5: datoteka je stisnjena s algoritmom PKWARE DCL Implode
2.7: datoteka je popravek (patch)
4.5: datoteka uporablja format ZIP64
Prakti�na uporaba algoritmov stiskanja podatkov 30
4.6: datoteka je stisnjena z algoritmom BZIP2
5.0: datoteka je zaš�itena (kodirana) z algoritmom DES
5.0: datoteka je zaš�itena (kodirana) z algoritmom 3DES
5.0: datoteka je zaš�itena (kodirana) z originalnim algoritmom RC2
5.0: datoteka je zaš�itena (kodirana) z algoritmom RC4
5.1: datoteka je zaš�itena (kodirana) z algoritmom AES
5.1: datoteka je zaš�itena (kodirana) s spremenjenim algoritmom RC2
5.2: datoteka je zaš�itena (kodirana) s spremenjenim algoritmom RC2-64
6.2: katalog je zaš�iten (kodiran)
6.3: datoteka je stisnjena z algoritmom LZMA
6.3: datoteka je stisnjena z algoritmom PPMd+
6.3: datoteka je zaš�itena (kodirana) z algoritmom BlowFish
6.3: datoteka je zaš�itena (kodirana) z algoritmom TwoFish
A.3: Zastavice (general purpose bit flag) 2 zloga
Bit 0: mora biti 1, �e je datoteka zaš�itena (kodirana)
Bit 1 in 2 (odvisno od uporabljenega algoritma stiskanja). Za algoritem Deflate:
00: uporabljen je normalni faktor stiskanja
01: uporabljen je maksimalni faktor stiskanja
10: uporabljeno je hitro stiskanje
11: uporabljeno je super hitro stiskanje
Bit 3: �e 1, ima datoteka tudi blok za dodatni opis
Bit 4: rezervirano za algoritem Deflate64
Bit 5: �e 1, je datoteka popravek (patch)
Bit 6: mora biti 1, �e je datoteka zaš�itena (kodirana) z naprednejšimi algoritmi,
npr. DES, 3DES, AES itd.
Bit 7, 8, 9 in 10: trenutno neuporabljeni, morajo biti 0
Bit 11: �e 1, je ime datoteke kodirano z UTF-8
Bit 12: rezervirano (PKWARE)
Bit 13 (se uporablja samo, �e je katalog zaš�iten): �e je 1, ozna�uje, da so
vrednosti v opisu datoteke maskirane (skrivanje pravih vrednosti)
Bit 14 in 15: rezervirano (PKWARE)
A.4: Uporabljen algoritem stiskanja (compression method) 2 zloga
0 brez stiskanja
1 Shrink (spremenjen algoritem LZW)
2 Reduce: uporabljen je faktor stiskanja 1
3 Reduce: uporabljen je faktor stiskanja 2
4 Reduce: uporabljen je faktor stiskanja 3
5 Reduce: uporabljen je faktor stiskanja 4
6 Implode
Prakti�na uporaba algoritmov stiskanja podatkov 31
7 Tokenizing
8 Deflate
9 Deflate64
10 PKWARE DCL Implode
11 Rezervirano (PKWARE)
12 BZIP2
13 Rezervirano (PKWARE)
14 LZMA
15 Rezervirano (PKWARE)
16 Rezervirano (PKWARE)
17 Rezervirano (PKWARE)
18 IBM TERSE
19 IBM LZ77
97 WavPack
98 PPMd ver. 1
A.5: �as zadnje spremembe (last modification file time) 2 zloga
�as v formatu MS-DOS
A.6: Datum zadnje spremembe (last modification file date) 2 zloga
Datum v formatu MS-DOS
A.7: Kontrolna koda (CRC-32) 4 zlogi
Glej poglavje 5
A.8: Velikost stisnjene datoteke (compressed size) 4 zlogi
A.9: Velikost originalne datoteke (uncompressed size) 4 zlogi
A.10: Dolžina imena datoteke (file name length) – FNAMELEN 2 zloga
A.11: Dolžina polja za dodatne podatke (extra field length) – EXTRALEN 2 zloga
A.12: Ime datoteke (file name) FNAMELEN
Ime datoteke (ki lahko vsebuje tudi relativno pot). Pot ne sme vklju�evati oznake
pogona ali diska. Lo�ilo med mapami mora biti »/«.
A.13: Dodatni podatki (extra field) EXTRALEN
Za razširitve, npr. �e želimo shraniti dodatne informacije o datoteki. Predpisana je
oblika: HEAD1+DATA1+HEAD2+DATA2…, pri �emer je HEAD definiran kot:
ID bloka (HEAD ID): 2 zloga
Dolžina bloka (HEAD LEN): 2 zloga
(B) Kodirani podatki (file data): datoteka mora biti kodirana z enim izmed
predpisanih algoritmov (glej A.4). Kodirani podatki takoj sledijo bloku (A) Opis
datoteke.
Prakti�na uporaba algoritmov stiskanja podatkov 32
(F) Katalog (central directory): katalog vseh datotek v arhivu ZIP. Služi za hiter
dostop do podatkov vseh datotek, ki se nahajajo v arhivu. Zgradba bloka je
naslednja:
• F.1: opis prve datoteke (file header 1)
• F.1: opis druge datoteke (file header 2)
• …
• F.1: opis N-te datoteke (file header N)
• F.2: [digitalni podpis]
F.1: opis datoteke v katalogu (file header): opis posamezne datoteke (za hiter
prikaz in dostop do podatkov datoteke).
F.1.1: ID bloka (central file header signature) 4 zlogi
Mora biti 02014b5016
F.1.2: Verzija programa (version made by) 2 zloga
Zgornji zlog (MSB) predstavlja kompatibilnost z operacijskim sistemom. Vrednosti
so predpisane in pomenijo slede�e:
0 MS-DOS in OS/2 (FAT, VFAT in FAT32)
1 Amiga
2 OpenVMS
3 UNIX
4 VM/CMS
5 Atari ST
6 OS/2 HP FS
7 MacIntosh
8 Z-system
9 CP/M
10 Windows NTFS
11 MVS
12 VSE
13 Acorn RISC
14 VFAT
15 Alternate MVS
16 BeOS
17 Tandem
Prakti�na uporaba algoritmov stiskanja podatkov 33
18 OS/400
19 OS/X
Spodnji zlog (LSB) predstavlja specifikacijo, ki jo program podpira. Npr. za verzijo
6.3 je LSB enak 63.
F.1.3: Minimalna verzija za dearhiviranje (version needed to extract) 2 zloga
Enako kot v A.2
F.1.4: Zastavice (general purpose bit flag) 2 zloga
Enako kot v A.3
F.1.5: Uporabljen algoritem stiskanja (compression method) 2 zloga
Enako kot v A.4
F.1.6: �as zadnje spremembe (last modification file time) 2 zloga
Enako kot v A.5
F.1.7: Datum zadnje spremembe (last modification file date) 2 zloga
Enako kot v A.6
F.1.8: Kontrolna koda (CRC-32) 4 zlogi
Enako kot v A.7
F.1.9: Velikost stisnjene datoteke (compressed size) 4 zlogi
F.1.10: Velikost originalne datoteke (uncompressed size) 4 zlogi
F.1.11: Dolžina imena datoteke (file name length) – FNAMELEN 2 zloga
F.1.12: Dolžina polja za dodatne podatke (extra field length) – EXTRALEN 2 zloga
F.1.13: Dolžina komentarja (file comment length) - COMMLEN 2 zloga
F.1.14: Za�etna številka segmenta (disk number start) 2 zloga
Številka segmenta (datoteke), kjer so dejanski podatki za datoteko iz tega bloka
F.1.15: Interni datote�ni atributi (internal file attributes) 2 zloga
Bit 0: �e 0, je datoteka binarna. �e 1, je datoteka tekstovna
Bit 1 in 2: rezervirano (PKWARE)
Ostali biti so neuporabljeni
F.1.16: Zunanji datote�ni atributi (external file attributes) 4 zlogi
Odvisno od operacijskega sistema
F.1.17: Odmik do podatkov datoteke (relative offset of local file header) 4 zlogi
Odmik, kjer se za�nejo podatki za datoteko iz tega bloka. Odmik kaže na za�etek
bloka A – opis datoteke (local file header) glede na F.1.14
F.1.18: Ime datoteke (file name) FNAMELEN
F.1.19: Dodatni podatki (extra field) EXTRALEN
F.1.20: Komentar (file comment) COMMLEN
Prakti�na uporaba algoritmov stiskanja podatkov 34
(I) Konec kataloga (end of central directory): dodatne informacije o arhivu ZIP.
I.1: ID bloka (end of central directory signature) 4 zlogi
Mora biti 06054b5016
I.2: Številka segmenta (number of this disk) 2 zloga
Številka segmenta (datoteke), ki vsebuje blok (I) Konec kataloga
I.3: Številka segmenta, kjer se za�ne katalog (number of disk with 2 zloga
the start of central directory): katalog se lahko razteza �ez ve� segmentov
(datotek), zato s tem poljem povemo, v katerem segmentu je za�etek kataloga
I.4: Število datotek v katalogu v tem segmentu (total number of entries 2 zloga
in the central directory on this disk)
I.5: Število vseh datotek v katalogu (total number of entries in the 2 zloga
central directory): število vseh datotek v celotnem arhivu, ne glede na to ali se
katalog razteza �ez ve� segmentov (datotek)
I.6: Velikost kataloga v zlogih (size of central directory) 4 zlogi
I.7: Odmik do za�etka kataloga (offset to start of central directory 4 zlogi
with respect to I.3)
I.8: Dolžina komentarja (ZIP file comment length) - COMMLEN 2 zloga
I.9: Komentar (ZIP file comment) COMMLEN
5 KODA CRC
Osnovni namen kode CRC (angl. cyclic redundancy code ali tudi cyclic
redundancy check) je ugotavljanje, ali je bilo dolo�eno sporo�ilo spremenjeno.
Sporo�ilo je lahko spremenjeno iz razli�nih razlogov: zaradi napake pri prenosu
(npr. preko omrežne povezave), zaradi napake medija (npr. pri zapisovanju na
disk ali branju z njega), pri prenosu od uporabnika A do uporabnika B bi ga lahko
spremenil uporabnik C itd. Torej služi kot neke vrste podpis.
Oddajnik iz vsebine sporo�ila izra�una kodo CRC in jo pripne k sporo�ilu. Na
drugi strani prejemnik iz prejetega sporo�ila prav tako izra�una kodo CRC. �e
dobi rezultat razli�en od ni�, lahko z gotovostjo trdi, da je bilo sporo�ilo
spremenjeno. V nasprotnem primeru je lahko skoraj stoodstotno gotov, da je
Prakti�na uporaba algoritmov stiskanja podatkov 35
sporo�ilo nespremenjeno. Stoodstotne zanesljivosti ne moremo dose�i, kajti
razli�na sporo�ila lahko tvorijo enako kodo CRC, na kar pa nimamo vpliva. Tako
dopuš�amo možnost, da bi tudi iz spremenjenega sporo�ila dobili enako kodo
CRC kot iz originala, vendar je verjetnost za kaj takega dovolj majhna, da jo lahko
zanemarimo.
�e si zamislimo, da je naše sporo�ilo dolgo binarno število, ga lahko delimo z
drugim binarnim številom, preostanek pa predstavlja kodo CRC. Obi�ajno obe
števili predstavimo kot polinoma. Deljenje polinomov je v matematiki dobro
poznano, v ra�unalništvu pa so si omislili številne poenostavljene aritmetike in eno
izmed njih uporabljamo tudi pri ra�unanju kode CRC. Imenujemo jo aritmetika
MOD 2, nekateri avtorji pa ji pravijo tudi aritmetika CRC. Ker ra�unamo v
dvojiškem sistemu, koeficienti ob spremenljivki odpadejo, saj so lahko le ni� ali
ena. Torej upoštevamo samo spremenljivke s koeficientom ena. Npr. binarno
število 10110012 lahko zapišemo kot polinom: 1 � X6 + 0 � X5 + 1 � X4 + 1 � X3 + 0 �
X2 + 0 � X1 + 1 � X0 = X6 + X4 + X3 + 1. Druga poenostavitev je, da vse ra�unske
operacije izvajamo brez prenosa. Ob teh predpostavkah lahko v naši aritmetiki
definiramo osnovne štiri operacije: seštevanje, odštevanje, množenje in deljenje.
Seštevanje Odštevanje
1010 1010
+ 1100 - 1100
0110 0110
Slika 5.1: Primer seštevanja in odštevanja dveh števil v aritmetiki CRC
Kot lahko opazimo, obe operaciji dajeta enak rezultat, hkrati pa zelo prikladno
sovpadata z drugim binarnim operatorjem, ki ga v ra�unalništvu dokaj pogosto
uporabljamo, t.j. operator XOR (⊕). Takšen rezultat ima za posledico še eno
zanimivo lastnost: primerjava dveh števil je možna samo na najvišjem koeficientu
(bitu).
Prakti�na uporaba algoritmov stiskanja podatkov 36
Primer: v aritmetiki CRC ne moremo trditi, da je število 10102 ve�je od števila 10012. Npr. 10102 +
00112 = 10012. Hkrati pa je tudi 10102 – 00112 = 10012. �e nekemu številu prištejemo konstanto, bi
pri�akovali, da bomo dobili neko ve�je število. Podobno, �e številu odštejemo isto konstanto,
pri�akujemo manjše število. V našem primeru pa dobimo obakrat enak rezultat, torej morata biti
števili enaki (kar je tudi res glede na prvi bit).
Množenje dveh števil A in B je tudi zelo preprosto. Tako kot v obi�ajni aritmetiki
ga lahko tudi v aritmetiki CRC prevedemo na vsoto. Število A množimo s
posameznimi biti števila B. Bite števila B beremo z desne proti levi (od najmanj
pomembnega bita b0 proti najbolj pomembnemu bitu bN). Po vsakem množenju
moramo tudi število A pomakniti za en bit v levo. Na koncu vse delne rezultate
seštejemo (spomnimo, da seštevanje izvedemo z operatorjem XOR).
Primer: pomnožimo števili A=10112 in B=1012. Prvi bit števila B je enak 1 (gledano z desne proti
levi), zato število 10112 enostavno prepišemo: 10112 � 1 = 10112. Število A pomaknemo za en bit v
levo in ga pomnožimo z drugim bitom števila B, ki je 0: 101102 � 0 = 000002. Število A spet
pomaknemo za en bit v levo in ga pomnožimo s tretjim bitom števila B: 1011002 � 1 = 1011002.
Ni�le, ki smo jih pridobili s pomikanjem števila v levo, smo ozna�ili s pikami.
1011 101�
10 110000 .
10 11 . .100111
Slika 5.2: Primer množenja dveh števil v aritmetiki CRC
Preverimo rezultat še z množenjem polinomov. Število A lahko zapišemo kot: X3 + X + 1, število B
pa kot: X2 + 1. �e pomnožimo (X3 + X + 1) � (X2 + 1), dobimo: X5 + X3 + X3 + X + X2 + 1 = X5 + X2 +
X + 1, kar je natanko naš rezultat: 1001112. Opozorimo še na to, kako smo izgubili oba �lena X3!
Seštevanje izvedemo z operacijo XOR: 1 � X3 ⊕ 1 � X3 = 0 � X3 = 0.
Pri deljenju dveh števil A : B moramo upoštevati pravilo, da sta dve števili
enaki, �e se ujemata na najvišjem bitu. Najvišji bit števila B (delitelja) je vedno
ena, ker vodilnih ni�el ne pišemo. Definirajmo deljenje. �e je najvišji bit števila A
Prakti�na uporaba algoritmov stiskanja podatkov 37
ni�, v rezultat zapišemo 0, odstranimi najvišji bit in nadaljujemo z deljenjem. �e je
najvišji bit števila A ena, v rezultat zapišemo 1, od A odštejemo B (XOR),
odstranimo najvišji bit in nadaljujemo z deljenjem. V bistvu je postopek enak
ro�nemu deljenju dveh števil, kot ga poznamo v matematiki, ob upoštevanju pravil
aritmetike CRC (ni prenosa; za operacijo odštevanja uporabimo operator XOR;
rezultat deljenja je 1, �e je najvišji bit števila, ki ga delimo, enak 1).
Primer: delimo število A=101011002 s številom B=1012. (A) 1012 : 1012 = 1 in ostanek je 0002. (B)
Najvišji bit ostanka odstranimo in pripišemo naslednji bit iz števila A: 0002. 0002 : 1012 = 0. (C)
Odstranimo najvišji bit ostanka in pripišemo naslednji bit števila A: 0012. 0012 : 1012 = 0. (D)
Odstranimo najvišji bit ostanka in pripišemo naslednji bit števila A: 0112. 0112 : 1012 = 0. (E)
Odstranimo najvišji bit ostanka in pripišemo naslednji bit števila A: 1102. 1102 : 1012 = 1 in ostanek
je 0112. (F) Odstranimo najvišji bit ostanka in pripišemo naslednji bit števila A: 1102. 1102 : 1012 = 1
in ostanek je 0112. (G) Odstranimo najvišji bit ostanka in ker nimamo ve� bitov v številu A, je
deljenje zaklju�eno. Torej je 101011002 : 1012 = 1000112, z ostankom 112.
10 11 0 01 1 1 00 : =1 0 1-0 0 0
0 0 00 0 1
0 1 11 1 010 1-0 1 1
1 1 0
1 0 0 0 1 1
1 0 1-0 1 1
1 1[ ]
(A)
(B)(C)(D)
(E)
(F)
(G)
Slika 5.3: Primer deljenja dveh števil v aritmetiki CRC
Opozorimo, da je rezultat deljenja vedno 1, �e je najvišji bit enak 1. Tako je 1012 : 1012 = 1, kot tudi
1102 : 1012 = 1 in tudi 1002 : 1012 = 1. Rezultat preverimo še s polinomi: (X5 + X + 1) � (X2 +1) = X7
+ X5 + X3 + X + X2 + 1 = X7 + X5 + X3 + X2 + X + 1. Prištejmo še ostanek (X + 1). Dobimo: X7 + X5 +
X3 + X2, kar je naše število A: 101011002.
Prakti�na uporaba algoritmov stiskanja podatkov 38
Z definiranjem operacije deljenja smo dobili osnovni postopek ra�unanja kode
CRC, ki je enaka ostanku pri deljenju. �e želimo, da bo tudi sprejemnik lahko
izra�unal enako kodo CRC, mora vedeti, kakšen je delitelj. Na�eloma je lahko
delitelj kakršenkoli, vendar je praksa pokazala, da so nekateri boljši od drugih. Ker
lahko delitelj prikažemo kot polinom, nam najvišja potenca polinoma pove stopnjo
delitelja. Najve�krat izbiramo delitelje stopnje šestnajst (CRC-16) ali dvaintrideset
(CRC-32), predvsem zaradi lažje prilagoditve algoritma sodobnim ra�unalnikom.
Nekateri avtorji delitelj imenujejo tudi magi�no število (angl. magic number).
Razlog za tako poimenovanje leži v tem, da nam delitelj predstavlja klju�ni
podatek za ra�unanje kode CRC. �e ne poznamo delitelja, ne moremo preveriti
pravilnost sporo�ila s priloženo kodo CRC.
Opis Magi�no število Razred ZIP datoteka DEBB20E316 CRC-32 Ethernet protokol 04C11DB716 CRC-32 X.25 protokol 102116 CRC-16 USB (universal serial bus) 800516 CRC-16
Tabela 5.1: Tabela nekaterih standardnih deliteljev
Opozorimo na to, da ostanek dolžine N bitov ustreza polinomu stopnje (N-1).
Ker pa je ostanek vedno vsaj za eno stopnjo nižji od delitelja, mora biti delitelj
stopnje N, ki zahteva (N+1) bitov. Vemo tudi, da je najvišji koeficient delitelja
vedno ena, zato ga ne pišemo.
Primer: pri CRC-32 je ostanek (naša koda CRC) dolžine 32 bitov in tako predstavlja polinom
stopnje 31 s koeficienti: b0 do b31. Ker je delitelj vedno ve�ji od najve�jega možnega ostanka, mora
biti stopnje 32, za kar potrebujemo 33 bitov: b0 do b32. Ker pa imajo sodobni ra�unalniki 32-bitne
procesorje, je 33-bitno število težko u�inkovito predstaviti. Vemo tudi, da je najvišji koeficient
delitelja b32 vedno 1, zato ga ne pišemo, preostanek pa predstavimo z 32-bitno vrednostjo.
Primer: kateri polinom predstavlja magi�no število za ZIP datoteko? �e magi�no število zapišemo
kot binarno število, dobimo: {1} 1101 1110 1011 1011 0010 0000 1110 00112. Najvišji bit b32, ki ga
ne pišemo, smo zapisali v zavitih oklepajih. Sledi: X32 + X31 + X30 + X28 + X27 + X26 + X25 + X23 + X21
+ X20 + X19 + X17 + X16 + X13 + X7 + X6 + X5 + X + 1.
Prakti�na uporaba algoritmov stiskanja podatkov 39
Preden se lahko lotimo ra�unanja kode CRC, uporabimo še eno ukano. Zaradi
lažjega razumevanja bo postopek opisan za 32-bitne kode CRC in nas bo privedel
do algoritma za ra�unanje kode CRC poljubne dolžine. S stališ�a ra�unanja bi bilo
najlažje, �e bi uporabljali 32-bitne delitelje. Vhodno sporo�ilo bi delili z deliteljem in
dobili 31-bitni ostanek. Vendar bi na ta na�in imeli samo 2147483648 (231)
razli�nih kod CRC, kar je dvakrat manj, kot jih dobimo ob uporabi 33-bitnega
delitelja: 4294967296 (232). Torej moramo najti na�in, kako 32-bitni delitelj
pretvoriti v 33-bitni tako, da nas ne bo oviral pri ra�unanju (ra�unanje s 33-bitnimi
vrednostmi ni ravno pisano na kožo sodobnim ra�unalnikom). Iz matematike
vemo, da se rezultat ne spremeni, �e obe strani izraza pomnožimo z isto
vrednostjo. V našem primeru naj bo ta vrednost X32, ki bo delitelj stopnje
enaintrideset spremenila v delitelj stopnje dvaintrideset (v praksi delitelja ne
množimo, ker je že podan kot polinom dvaintridesete stopnje). Pomnožiti moramo
tudi vhodno sporo�ilo, kar pa je v resnici zelo lahko: na konec sporo�ila pripnemo
niz dvaintridesetih ni�el.
Zapišimo še formalno ena�bo. Naj bo naše sporo�ilo polinom S(x), delitelj D(x),
celoštevil�ni rezultat deljenja S(x) : D(x) = K(x) in ostanek O(x). Tedaj lahko
zapišemo:
S(x) � X32 = K(x) � D(x) + O(x) (5.1)
�e vhodnemu sporo�ilu pripnemo ostanek (kodo CRC), dobimo na sprejemni
strani:
S(x) � X32 + O(x) = K(x) � D(x) (5.2)
Ob predpostavki, da je prenos sporo�ila potekal brez napak, moramo na sprejemni
strani dobiti kodo CRC 0, saj je vhodno sporo�ilo z dodanim ostankom v celoti
deljivo z deliteljem D(x). Zapišimo še splošni algoritem:
Prakti�na uporaba algoritmov stiskanja podatkov 40
1. Inicializiraj delitelj: unsigned long D = predpisani delitelj
2. Na konec sporo�ila dodaj N ni�el, kjer je N število bitov kode CRC (množimo z XN )
3. Inicializiraj Code na 0: unsigned long Code = 0
4. Obdelaj celotno sporo�ilo:
while (ni konec sporo�ila)
{
zapomni si najvišji bit v Code: bN
pomakni Code v levo za en bit (odstrani najvišji bit)
preberi naslednji bit sporo�ila in ga vstavi v Code na bitu b0
if (bN == 1)
Code = Code XOR D
}
5. Code vsebuje ostanek: kodo CRC
Morda na prvi pogled ni jasno, kako zgornji algoritem izvaja deljenje. �e se
spomnimo primera, ko smo ro�no delili dve števili, smo odšteli delitelj vsaki�, ko je
bil najvišji bit enak 1. Prav to po�nemo tudi tukaj: delitelj odštejemo z operacijo
XOR.
�e bo bralec iskal algoritem za ra�unanje kode CRC v literaturi ali na internetu,
bo ugotovil, da ni niti malo podoben zgornjemu algoritmu. Zgornji algoritem je
splošen in primeren za ra�unanje kakršnekoli kode CRC, vendar ima o�itno
slabost: obdeluje en bit naenkrat. Za u�inkovito ra�unanje kode CRC potrebujemo
algoritem, ki bo hitro vrnil rezultat tudi za zelo dolga sporo�ila, npr. datoteke z
dolžinami nekaj MB. Ker je operacija XOR asociativna, t.j. vrstni red izvajanja
operacij XOR ni pomemben, je možno algoritem popraviti tako, da naenkrat
obdela cel zlog. Da proces pospešimo, si prej za vsak znak [0..255] izra�unamo
kodo CRC in jo shranimo v tabelo. Sledi algoritem za inicializacijo tabele:
unsigned long table[255];
unsigned long D = predpisani delitelj;
for (unsigned long i = 0; i < 256; i++)
{
unsigned long Code = i << 24; // Znak i pomaknemo v MSB
for (int j = 0; j < 8; j++) // Za vsak bit znaka
Prakti�na uporaba algoritmov stiskanja podatkov 41
{
bool topBit = (Code & 0x80000000) != 0;
Code <<= 1; // Pomaknemo se na naslednji bit
if (topBit) // Najvišji bit je bil 1
Code ^= D; // Odštejemo delitelj
}
table [i] = Code; // koda CRC za znak i
}
Popravljeni algoritem za izra�un kode CRC je sedaj naslednji:
1. Inicializiraj delitelj: unsigned long D = predpisani delitelj
2. Inicializiraj tabelo: table[255] tako, da uporabiš osnovni algoritem za vsak znak [0..255]
3. Na konec sporo�ila dodaj N ni�el, kjer je N število bitov kode CRC (množimo z XN )
4. Inicializiraj Code na 0: unsigned long Code = 0
5. Obdelaj celotno sporo�ilo:
while (ni konec sporo�ila)
{
byte top= (Code >> 24) & 0xFF; // Najvišji byte v Code
Code = (Code << 8); // Odstrani najvišji byte v Code
Code = Code | naslednji zlog sporo�ila; // Naslednji zlog sporo�ila
Code = Code XOR table[top];
}
6. Code vsebuje ostanek: kodo CRC
V jeziku C++ celotno vsebino zanke while obi�ajno zapišemo v enem stavku, pri
�emer je *p kazalec na naše vhodno sporo�ilo, operator ^ pa operator XOR:
Code = ((Code << 8) | *p++) ^ table[(Code >> 24) & 0xFF] oziroma
Code = ((Code << 8) | *p++) ^ table[(Code >> 24)]
�eprav zgornji algoritem deluje popolnoma pravilno in bi ga težko še bolj strnili,
pa so nekateri avtorji našli še nekaj prostora za optimizacijo. Na za�etku je Code
enak 0 (0000000016), zato potrebujemo štiri prazne cikle, preden pridemo do
zlogov sporo�ila (spomnimo, da v vsaki ponovitvi zanke odstranimo najvišji zlog).
Druga slabost je, da moramo sporo�ilo najprej dopolniti z ni�lami na koncu:
Prakti�na uporaba algoritmov stiskanja podatkov 42
množenje z XN. Spet se izkaže, da sta oba koraka nepotrebna, �e stavek znotraj
zanke while malo popravimo:
Code = (Code << 8) ^ table[(Code >> 24) ^ *p++]
Zgornji stavek bomo najpogosteje sre�ali v literaturi, v�asih pa tudi obrnjeno
razli�ico. �e delitelj obrnemo, tako da ima na levi strani najmanj pomemben bit b0,
na desni pa najbolj pomembnega bN, je možno zgornji stavek še malo optimizirati:
Code = (Code >> 8) ^ table[Code ^ *p++]
Ker je najbolj pomemben zlog sedaj na desni, moramo bite pomikati v desno.
Prednost pa je v tem, da ne potrebujemo nobenega pomika, da pridemo do
najvišjega zloga (prej: Code >> 24). Kadar uporabljamo obrnjeno razli�ico
algoritma, moramo tudi pri ra�unanju tabele upoštevati pomik bitov v desno.
Zapišimo kon�no verzijo algoritma:
1. Inicializiraj delitelj: unsigned long D = predpisani delitelj
2. Inicializiraj tabelo: table[255] tako, da uporabiš osnovni algoritem za vsak znak [0..255]
3. Inicializiraj Code na 0: unsigned long Code = 0
4. Obdelaj celotno sporo�ilo:
while (ni konec sporo�ila)
Code = (Code << 8) ^ table[(Code >> 24) ^ *p++]
5. Code vsebuje ostanek: kodo CRC
6 IMAPI
IMAPI (angl. Image Mastering API) je programski vmesnik, ki omogo�a
zapisovanje podatkov na medije CD in DVD. Programski vmesnik je na voljo od
operacijskega sistema Windows XP dalje, za starejše operacijske sisteme pa
funkcionalnost ni podprta. Obstajata dve razli�ici:
Prakti�na uporaba algoritmov stiskanja podatkov 43
• IMAPI 1.0: je na voljo v operacijskih sistemih Windows XP in Windows
Server 2003. Omogo�a zapisovanje na medije CD, ne pa tudi na medije
DVD.
• IMAPI 2.0: na voljo v operacijskih sistemih Windows Vista in Windows
Server 2008. Omogo�a zapisovanje na medije CD in DVD. Za
operacijska sistema Windows XP in Windows Server 2003 obstajata
dodatka, ki omogo�a enako funkcionalnost, vendar ju je potrebno
posebej namestiti.
IMAPI 2.0 podpira zapis na naslednje vrste opti�nih medijev: CD-R, CD-RW,
DVD-R, DVD+R, DVD-RW, DVD+RW, DVD-RAM ter dvoplastni DVD-R in
DVD+R. Prav tako podpira naslednje oblike zapisa: ISO 9660, Joliet in UDF.
Struktura datote�nega sistema na CD-ju ali DVD-ju omogo�a, da lahko imamo vse
tri hkrati na istem mediju. Program za predvajanje potem sam izbere tisto obliko, ki
mu najbolj ustreza. To je možno zaradi tega, ker so razli�na samo kazala, ki
pripadajo posamezni obliki zapisa, vsebina (npr. glasba, program, slike itd.) pa je
enaka. Kazalo vsebuje seznam datotek, ki so shranjene na mediju. V podrobnosti
standardov se na tem mestu ne bomo spuš�ali, bralec lahko podroben opis najde
v [9] in [10].
6.1 Znani problemi
�e želimo uporabljati IMAPI 2.0 v okolju Windows XP, moramo ustrezen
dodatek posebej namestiti. Dodatek se dobi na Microsoftovih straneh za podporo
in se imenuje WindowsXP-KB932716-v2-x86-ENU.exe. Ob namestitvi se v mapo
C:\Windows\System32\ shranita dve sistemski knjižnici: imapi2.dll in imapi2fs.dll,
vse javno vidne komponente iz obeh knjižnic pa se zapišejo v sistemski register.
Za IMAPI ne obstaja programska knjižnica (angl. type library), zato
programiranje z IMAPI ni možno v jezikih, ki zahtevajo strogo deklaracijo
spremenljivk. Razlog je zelo preprost: ker tipov ni možno uvoziti, jih tudi ni možno
uporabljati. Izjema je programski jezik C++. Za C++ so na voljo datoteke .h, kjer so
Prakti�na uporaba algoritmov stiskanja podatkov 44
deklaracije vseh vmesnikov: imapi2.h in imapi2fs.h.
Na�eloma bi lahko IMAPI programirali tudi v ogrodju .Net, npr. v programskem
jeziku C#. V ogrodju .Net je z dodajanjem povezav na zunanje knjižnice (angl. Add
reference) možno uvoziti obe sistemski knjižnici: imapi2.dll in imapi2fs.dll. Ob
uvozu se kreira dodatni vmesnik, ki služi zgolj za komunikacijo med kodo,
napisano v ogrodju .Net (angl. managed code) in kodo, ki pripada komponentam
IMAPI. Ker pa ogrodje .Net zahteva strogo lo�evanje razredov po imenskih
podro�jih, se pri uvozu glede na knjižnico vmesniki razdelijo na dve imenski
podro�ji: IMAPI2 in IMAPI2FS. Ve�ina vmesnikov in njihovih funkcij deluje dobro.
Težave nastanejo, kadar moramo posredovati vmesnik iz enega imenskega
podro�ja v drugega. Takrat prevajalnik javi napako, �eprav napake v bistvu ni.
Primer: �e želimo zapisati podatke na CD, moramo v vmesniku IDiscFormat2Data klicati metodo
Write(IStream* stream), pri �emer je stream binarna datoteka. Binarno datoteko tvori drug vmesnik
IFileSystemImage preko metode CreateResultImage(). Ker sta oba vmesnika vsak v svojem
imenskem podro�ju, Write() zahteva, da je stream tipa IMAPI2.IStream, IFileSystemImage pa
vra�a IMAPI2FS.IStream.
Vse probleme je možno rešiti tako, da IMAPI programiramo v jeziku C++. Ker
pa želimo programirati v ogrodju .Net, je najbolje, da v jeziku C++ napišemo
komponento, ki bo služila kot vmesnik med IMAPI in programom, napisanim v C#
ali Visual Basic .Net. V tem vmesniku bomo definirali metode, ki nam bodo
posredno omogo�ale dostop do funkcij IMAPI.
Ena izmed metod komuniciranja med razli�nimi aplikacijami v okolju Windows
je uporaba OLE (angl. Object Linking And Embedding). OLE omogo�a urejanje
dokumentov, ki so nastali v drugih aplikacijah, npr. v svoji aplikaciji lahko
omogo�imo urejanje Excelove preglednice. OLE združuje dve vrsti objektov: tiste,
ki imajo grafi�ni vmesnik in jih je možno videti na zaslonu (v obliki komponent
ActiveX) in tiste, ki zagotavljajo zgolj neko funkcionalnost in grafi�nega vmesnika
ne potrebujejo (v obliki komponent COM). OLE ima mnogo prednosti, ima pa tudi
zelo veliko slabost. �e želimo uporabiti katerikoli objekt OLE, ga moramo najprej
Prakti�na uporaba algoritmov stiskanja podatkov 45
registrirati (vpisati v sistemski register ra�unalnika). Obi�ajno registracijo opravi
namestitveni program, možno pa jo je izvesti tudi ro�no. V mapi
C:\Windows\System32\ se nahaja program regsvr32.exe, ki mu je potrebno
posredovati ime knjižnice, ki jo želimo registrirati.
Primer: �e se komponenta nahaja v knjižnici c:\programabc\abc.dll, jo ro�no registriramo z ukazom:
c:\windows\system32\regsvr32.exe c:\programabc\abc.dll.
Za dostop do funkcionalnosti IMAPI ne potrebujemo grafi�nega vmesnika, zato
bomo napisali komponento COM. V jeziku C++ je komponente COM najlaže
napisati s pomo�jo knjižnice ATL (angl. Active Template Library). ATL vsebuje
izbran nabor generi�nih razredov (isti razred lahko uporabimo nad razli�nimi tipi
podatkov). Zaradi tega je kode malo in se izvaja hitro.
6.2 Vmesniki IMAPI
IMAPI omogo�a zelo natan�no kontrolo nad procesom zapisovanja podatkov
na medije CD/DVD. Vsebuje osemintrideset vmesnikov, od tega je za osnovni
zapis potrebnih šest:
• IDiscMaster2: dostop do osnovnih podatkov o nameš�enih pogonih
CD/DVD (število pogonov in enoli�na oznaka vsakega pogona).
• IDiscRecorder2: predstavlja fizi�ni pogon CD/DVD. Omogo�a dostop do
informacij o pogonu (ime, proizvajalec, �rka pogona, lastnosti itd.) ter
odpiranje in zapiranje pogona.
• IFileSystemImage: pretvori strukturo map in datotek, ki jih želimo
zapisati na medij CD/DVD, v obliko, primerno za zapis - slika zapisa.
• IFileSystemImageResult: pretvorjena oblika za zapis.
• IFsiDirectoryItem: predstavlja mapo in datoteke v njej (podobno strukturi
map in datotek na disku).
• IDiscFormat2Data: zapiše podatke na medij CD/DVD.
Prakti�na uporaba algoritmov stiskanja podatkov 46
IDiscMaster2: je vmesnik za dostop do podatkov o nameš�enih pogonih CD/DVD.
Kreiramo ga z ukazom:
CComPtr<IDiscMaster2> dm;
HRESULT hr = dm.CoCreateInstance(CLSID_MsftDiscMaster2);
(a) get_Count(): vrne število nameš�enih pogonov CD/DVD.
HRESULT get_Count
(
[out] LONG* value // vrne št. Pogonov
);
(b) get_Item(): vrne enoli�no oznako pogona (ID).
HRESULT get_Item
(
[in] LONG index, // zaporedna št. Pogona, >= 0
[out] BSTR* value // vrne id pogona
);
IDiscRecorder2: je vmesnik, ki predstavlja posamezni fizi�ni pogon CD/DVD.
Kreiramo ga z ukazom:
CcomPtr<IdiscRecorder2> dr;
HRESULT hr = dr.CoCreateInstance(CLSID_MsftDiscRecorder2);
(a) InitializeDiscRecorder():poveže vmesnik s fizi�nim pogonom CD/DVD.
HRESULT InitializeDiscRecorder
(
[in] BSTR id // ID pogona (ki ga vrne IdiscMaster2)
);
IFileSystemImage: vmesnik, ki pretvori mape in datoteke, ki jih želimo zapisati na
medij CD/DVD, v obliko, primerno za zapis. Kreiramo ga z ukazom:
CcomPtr<IfileSystemImage> im;
HRESULT hr = im.CoCreateInstance(CLSID_MsftFileSystemImage);
Prakti�na uporaba algoritmov stiskanja podatkov 47
(a) get_Root(): vrne korensko mapo. V to mapo dodajamo ostale mape in datoteke, ki jih želimo
zapisati na medij CD/DVD.
HRESULT get_Root
(
[out] IfsiDirectoryItem** dir // vrne korensko mapo
);
(b) SetMaxMediaBlocksFromDevice(): vmesnik vpraša zapisovalnik po številu prostih blokov.
HRESULT SetMaxMediaBlocksFromDevice
(
[in] IdiscRecorder2* rec // zapisovalnik
);
(c) put_FileSystemToCreate(): povemo, katere oblike zapisa želimo kreirati: ISO 9660, Joliet ali
UDF. Možne so tudi kombinacije vseh treh. FsiFileSystems je naštevalni tip in je definiran:
FsiFileSystemNone=0, FsiFileSystemISO9660=1, FsiFileSystemJoliet=2, FsiFileSystemUDF=4,
FsiFileSystemUnknown=0x40000000.
HRESULT put_FileSystemsToCreate
(
[in] FsiFileSystems value // ISO9660, Joliet, UDF
);
(d) put_VolumeName(): povemo ime medija CD/DVD. Ime je vidno v Raziskovalcu, kadar je
medij vstavljen v pogon.
HRESULT put_VolumeName
(
[in] BSTR name // ime medija
);
(e) CreateResultImage(): pretvori mape in datoteke v obliko, primerno za zapis.
HRESULT CreateResultImage
(
[out] IfileSystemImageResult ** res // vrne obliko, primerno za zapis
);
Prakti�na uporaba algoritmov stiskanja podatkov 48
IFileSystemImageResult: vmesnik, ki omogo�a dostop do binarne datoteke, ki se
bo zapisala na medij CD/DVD. Datoteka je že v obliki, primerni za zapis. Objekta
ne moremo kreirati, dobimo ga kot rezultat metode CreateResultImage().
(a) get_ImageStream(): vrne binarno datoteko, do katere dostopamo preko vmesnika Istream.
HRESULT get_ImageStream
(
[out] Istream** stream // vrne binarno datoteko
);
IFsiDirectoryItem: vmesnik, ki omogo�a gradnjo datote�nega sistema (map in
datotek), ki jih bomo zapisali na medij CD/DVD. Vmesnika ni mogo�e kreirati,
dobimo ga kot rezultat razli�nih metod.
(a) AddTree(): v IfsiDirectoryItem doda celotno mapo, z vsemi podmapami in datotekami.
HRESULT AddTree
(
[in] BSTR path, // pot do mape
[in] BOOL include // TRUE, �e naj se mapa doda kot
); // podmapa
(b) AddDirectory(): v IFsiDirectoryItem doda mapo.
HRESULT AddDirectory
(
[in] BSTR path // ime mape
);
(c) AddFile(): v IFsiDirectoryItem doda datoteko.
HRESULT AddFile
(
[in] BSTR path, // pot do mape
[in] IStream* stream // datoteka
);
Prakti�na uporaba algoritmov stiskanja podatkov 49
IDiscFormat2Data: vmesnik, ki omogo�a zapis. Kreiramo ga z ukazom:
CComPtr<IDiscFormat2Data> dw;
HRESULT hr = dw.CoCreateInstance(CLSID_MsftDiscFormat2Data);
(a) Write(): zapiše podatke na medij CD/DVD.
HRESULT Write
(
[in] IStream* stream // datoteka, ki jo želimo zapisati
);
(b) put_ClientName(): ime programa, ki dostopa do zapisovalnika. Ime se mora ujemati z
imenom programa zaradi tega, ker se pri zapisovanju zahteva ekskluzivni dostop do
zapisovalnika (�eprav Microsoft trdi, da je lahko ime kakršnokoli, se izkaže, da mora biti enako
imenu programa, druga�e ekskluzivni dostop do zapisovalnika ni možen).
HRESULT put_ClientName
(
[in] BSTR name // ime programa
);
(c) put_Recorder(): povežemo zapisovalnik s fizi�nim pogonom CD/DVD.
HRESULT put_Recorder
(
[in] IDiscRecorder2* rec // fizi�ni pogon CD/DVD
);
Primer: preprostega programa, ki bo zapisal podatke na CD. Da bo primer bolj pregleden, bomo
zapisali zgolj osnovni postopek, brez obravnave napak, deklaracij metod itd. Preden nadaljujemo,
moramo v projektu v seznam datotek .h (»Header files«) dodati datoteki imapi2.h in imapi2fs.h (�e
imamo Windows XP in smo namestili dodatek, bi jih morali najti v mapi: C:\Program Files\Microsoft
SDKs\Windows\v6.1\Include\).
#include »imapi2.h« #include »imapi2fs.h« HRESULT hr=S_OK; CComBSTR volname("Test_ATL"); CComBSTR path("C:\\Temp\\Slike"); CComBSTR client(theApp.m_pszAppName); CComBSTR id;
Prakti�na uporaba algoritmov stiskanja podatkov 50
CComPtr<IDiscMaster2> dm; CComPtr<IDiscRecorder2> dr; CComPtr<IFileSystemImage> im; CComPtr<IDiscFormat2Data> dw; CComPtr<IFsiDirectoryItem> root=NULL; CComPtr<IFileSystemImageResult> res=NULL; CComPtr<IStream> stream=NULL; hr=dm.CoCreateInstance(CLSID_MsftDiscMaster2); hr=dr.CoCreateInstance(CLSID_MsftDiscRecorder2); hr=im.CoCreateInstance(CLSID_MsftFileSystemImage); hr=dw.CoCreateInstance(CLSID_MsftDiscFormat2Data); hr=dm->get_Item(0,&id); hr=dr->InitializeDiscRecorder(id); hr=dw->put_Recorder(dr); hr=dw->put_ClientName(client); hr=im->put_VolumeName(volname); hr=im->SetMaxMediaBlocksFromDevice(dr); hr=im->put_FileSystemsToCreate(FsiFileSystems::FsiFileSystemISO9660); hr=im->get_Root(&root); hr=root->AddTree(path,TRUE); hr=im->CreateResultImage(&res); hr=res->get_ImageStream(&stream); hr=dw->Write(stream);
Prakti�na uporaba algoritmov stiskanja podatkov 51
7 PROGRAM
Zahteve programa so že od samega za�etka bile, da mora podpirati ve�
razli�nih opravil: arhiviranje, obnovitev podatkov iz arhiva in zapisovanje na medije
CD/DVD. Upoštevali smo tudi možnost, da bo potrebno program neko� nadgraditi
in dodati funkcionalnost, ki trenutno ni podprta. Zato je program zgrajen
modularno.
7.1 Razredni diagrami
Strukturo smo si zamislili tako, da ima vsako opravilo svoj nabor razredov.
Razredi so razdeljeni po imenskih podro�jih (angl. Namespace). Ker se nahajajo v
lo�eni knjižnici, imenovani DipZipClasses, jih lahko enostavno vklju�imo v druge
projekte. To je možno tudi zaradi tega, ker smo se pri razvoju strogo držali pravila,
da morajo razredi predstavljati zgolj programsko logiko. Na ta na�in smo dosegli
neodvisnost med funkcionalnim in predstavitvenim delom programa.
DipZipClasses
Docs
Document
DocumentFolderDocumentItem
DocumentRoot
DocumentItemProgramDocumentItemArchiveDocumentItemDearchiveDocumentItemBackupDocumentItemBackupSettings
Zip
ZipArchiveZipCodecZipFileHeaderZipLocalFileHeaderZipEndOfCentralDir
Burn
BurnManager
Slika 7.1.1: Imenska podro�ja in razredi knjižnice DipZipClasses
Prakti�na uporaba algoritmov stiskanja podatkov 52
Imensko podro�je »Docs«: program shranjuje nastavitve v datoteko (dokument).
Razredi v imenskem podro�ju »Docs« nam omogo�ajo ravnanje z dokumenti:
odpiranje, shranjevanje in vzpostavljanje hierarhi�ne strukture dokumenta. Ker
nam služijo zgolj za predstavitev in urejanje opravil, jih na tem mestu ne bomo
podrobneje opisovali.
Slika 7.1.2: Razredni diagram (dokument)
Prakti�na uporaba algoritmov stiskanja podatkov 53
Imensko podro�je »Zip«: za kreiranje oz. odpiranje arhivskih datotek Zip
uporabljamo razred ZipArchive. Ostali razredi so pomožni in predstavljajo
posamezne gradnike datoteke ZIP.
Slika 7.1.3: Razredni diagram (arhiviranje)
Programski vmesnik razreda ZipArchive:
Public Property ExtractTo() As String
Mapa (celotna pot), kamor se bodo shranile datoteke pri obnovitvi podatkov.
Public Property ExtractWhat() As String
Ime datoteke ali vzorec, ki dolo�a, katere datoteke bodo obnovljene iz arhiva ZIP.
Privzeta vrednost je *.* za obnovitev vseh datotek v arhivu.
Prakti�na uporaba algoritmov stiskanja podatkov 54
Public Property Filename() As String
Ime (celotna pot) datoteke ZIP.
Public ReadOnly Property FilenameVersion() As String
Vrne ime datoteke ZIP z dodano verzijo datoteke. �e pri arhiviranju datoteka ZIP
že obstaja in je ne smemo prepisati, se dolo�i novo ime tako, da se na konec
prvotnega imena pripne verzija. Verzije se ozna�ujejo z A, B, C itd.
Public Property Overwrite() As Boolean
Nastavitev, ali lahko pri arhiviranju datoteko ZIP prepišemo, �e že obstaja.
Vrednost TRUE dolo�a, da se datoteka prepiše. Privzeta vrednost je FALSE;
datoteke ne smemo prepisati.
Public Sub AddArchiveCopy(ByVal Path As String)
Doda mapo v seznam map za dodatne kopije arhivske datoteke. Po arhiviranju je
možno shraniti dodatno kopijo arhivske datoteke v razli�ne mape, npr. na drug
disk ali ra�unalnik. Parametri:
• Path: mapa (celotna pot), kamor naj se po arhiviranju shrani dodatna kopija
arhivske datoteke.
Public Sub AddExclude(ByVal Path As String, ByVal Subfolders As Boolean)
V seznam doda ime datoteke ali vzorec, ki pove, katere datoteke naj program pri
arhiviranju presko�i. Parametri:
• Path: ime datoteke ali vzorec, npr. C:\Programi\*.exe
• Subfolders: vrednost TRUE dolo�a, da program preiš�e tudi vse podmape
Public Sub AddInclude(ByVal Path As String, ByVal Subfolders As Boolean)
V seznam doda ime datoteke ali vzorec, ki pove, katere datoteke naj program
arhivira. Parametri:
• Path: ime datoteke ali vzorec, npr. C:\Programi\*.*
Prakti�na uporaba algoritmov stiskanja podatkov 55
• Subfolders: vrednost TRUE dolo�a, da program preiš�e tudi vse podmape
Public Function Create() As Boolean
Kreira datoteko ZIP. �e je arhiviranje potekalo brez napak, vrne vrednost TRUE,
druga�e FALSE.
Public Function Extract() As Boolean
Obnovi datoteke iz arhiva ZIP. �e so bile vse datoteke v arhivu uspešno
obnovljene, vrne vrednost TRUE, druga�e FALSE.
Primer: opišimo, kako s programom izvedemo arhiviranje. Arhivirati želimo datoteko
C:\FERI\Diploma\Diploma.doc in podatke v mapi C:\Programi z vsemi podmapami, vendar ne
želimo arhivirati programov. Arhivska datoteka se bo imenovala Podatki_20090618.ZIP in jo želimo
kreirati v mapi C:\Arhiv. Dodatno kopijo arhivske datoteke želimo imeti v mapi F:\Backup, ki se
nahaja na izmenljivem disku.
Dim Zip As ZipArchive=New ZipArchive Zip.Filename="C:\Arhiv\Podatki_20090618.zip" Zip.AddArchiveCopy("F:\Backup\") Zip.AddInclude("C:\FERI\Diploma\Diploma.doc", False) Zip.AddInclude("C:\Programi\*.*", True) Zip.AddExclude("C:\Programi\*.exe", True) Zip.Create()
Za obnovitev datotek iz arhivske datoteke v mapo C:\Temp pišemo:
Dim Zip As ZipArchive=New ZipArchive Zip.Filename="C:\Arhiv\Podatki_20090618.zip" Zip.ExtractWhat="*.*" Zip.ExtractTo="C:\Temp\" Zip.Overwrite=True Zip.Extract()
Imensko podro�je »Burn«: zaradi znanih problemov pri uvozu knjižnic IMAPI v
ogrodje .Net smo morali dostop do vmesnikov IMAPI zagotoviti v jeziku C++.
Napisali smo komponento ATL COM, ki jo lahko uvozimo v ogrodje .Net in preko
nje posredno omogo�ili funkcionalnost zapisovanja na medije CD/DVD. Razred
BurnManager olajša komunikacijo med programom in komponento ATL COM.
Prakti�na uporaba algoritmov stiskanja podatkov 56
Slika 7.1.4: Razredni diagram (zapisovanje na medij CD/DVD)
Programski vmesnik razreda BurnManager:
Public ReadOnly Property LastError() As String
Vrne opis napake. IMAPI vra�a kodo napake, zato smo v komponenti ATL COM
poskrbeli za uporabniku bolj prijazen opis napake.
Public ReadOnly Property ListOfRejectedFiles() As List(Of
DipZipClasses.Docs.DocumentFile)
Vrne seznam zavrnjenih datotek. Pri dodajanju datotek v sliko IMAPI zapisa se
lahko zgodi, da je velikost datoteke ve�ja kot pa je prostora na mediju CD/DVD.
Public Property SelectedRecorder() As Integer
Zaporedna številka pogona CD/DVD, ki bo uporabljen pri zapisovanju. IMAPI
dostopa do pogonov preko številke pogona.
Public Property SessionLabel() As String
Oznaka seje zapisovanja. Ker je omogo�eno ve�kratno snemanje, lahko ima
vsako seja svojo oznako. Oznaka je vidna v Raziskovalcu, ko vstavimo medij
CD/DVD v pogon.
Public Sub AddFile(ByVal Path As String, Optional ByVal Subfolders As
Boolean = False)
V seznam datotek, ki �akajo na zapis, doda ime datoteke. Parametri:
Prakti�na uporaba algoritmov stiskanja podatkov 57
• Path: ime datoteke (polna pot)
• Subfolders: vrednost TRUE dolo�a, da program preiš�e tudi vse podmape
Public Function Burn() As Boolean
Zapiše datoteke na medij CD/DVD.
Public Sub Clear()
Pripravi BurnManager na novo sejo zapisovanja.
Public Function ListOfBurnDevices() As List(Of String)
Vrne seznam imen vseh pogonov CD/DVD, ki omogo�ajo zapisovanje.
Primer: opišimo, kako s programom izvedemo zapisovanje na medij CD/DVD. Zapisali bomo
arhivsko datoteko C:\Arhiv\Podatki_20090618.ZIP in sliko C:\Slike\LogarskaDolina.jpg. Ime seje
zapisovanja naj bo Podatki.
Dim Burner As BurnManager=New BurnManager Burner.Clear() Burner.SelectedRecorder=0 Burner.SessionLabel="Podatki" Burner.AddFile("C:\Arhiv\Podatki_20090618.zip") Burner.AddFile("C:\Slike\LogarskaDolina.jpg") Burner.Burn()
7.2 Predstavitev delovanja programa
Pri razvoju programa smo najve�ji poudarek namenili enostavnosti uporabe.
Program je smiselno razdeljen v štiri skupine opravil: zagon programov,
arhiviranje, obnovitev podatkov iz arhiva in kopiranje na CD/DVD. Vsaka skupina
je predstavljena z velikim gumbom. Kratek opis daje uporabniku namig glede
namembnosti.
Vse nastavitve je možno shraniti v datoteko (dokument). Program si zapomni
zadnji odprt dokument in ga ob naslednjem zagonu samodejno prebere. S tem
smo manj veš�im uporabnikom omogo�ili, da lahko takoj za�nejo z delom. Bolj
Prakti�na uporaba algoritmov stiskanja podatkov 58
izkušeni uporabniki pa imajo na voljo tudi ukaze za ravnanje z dokumenti:
kreiranje novega dokumenta, odpiranje že obstoje�ega dokumenta, shranjevanje
sprememb in shranjevanje dokumenta pod drugim imenom (kopija dokumenta).
Ime dokumenta je vidno v naslovni vrstici okna.
Slika 7.2.1: Pozdravno okno programa
Dokument je možno organizirati v sistem map in podmap, ki jih lahko uporabnik
poljubno odpira in s tem doseže ve�jo preglednost. Uporabniški vmesnik je, ne
glede na opravilo, vedno enak in ga je enostavno osvojiti. Na levi strani okna so
prikazane mape, na desni pa vsa opravila, ki se nahajajo v izbrani mapi. Za lažje
prepoznavanje vsako opravilo prikaže ime in kratek opis. Pri programih je dodatno
prikazana še ikona programa. Opis se z ve�jimi �rkami izpiše tudi v statusni vrstici
na dnu okna, �e potujemo s kazalcem miške preko opravila. Opravilo poženemo z
dvoklikom miške ali z izbiro iz kontekstnega menuja.
Prakti�na uporaba algoritmov stiskanja podatkov 59
Slika 7.2.2: Okno z opravili za zagon programov
Izbrana mapa oz. vsa izbrana opravila so obarvana oranžno in se jasno lo�ijo
od ostalih elementov. Medtem ko lahko izberemo samo posamezno mapo, pri
opravilih te omejitve ni. Izbiranje ve� opravil je v skladu s standardi v okolju
Windows:
• s tipko SHIFT in klikom miške za izbiranje ve� zaporednih elementov
hkrati.
• s tipko CTRL in klikom miške za izbiranje posameznih elementov.
Na vrhu okna smo dodali priro�en menu, ki uporabniku omogo�a, da od
koderkoli doseže vse funkcije programa z enim klikom miške. Tako mu ni treba
nazaj na prvo stran, da bi zamenjal opravilo.
Zagon programov in datotek: omogo�a hiter dostop do najpogosteje
uporabljanih programov in datotek. Program/datoteka se odpre v novem oknu.
Arhiviranje podatkov: na enostaven na�in arhiviramo podatke (datoteke), ne da
Prakti�na uporaba algoritmov stiskanja podatkov 60
bi pri tem morali poznati podrobnosti. Napredek arhiviranja lahko opazujemo v
novem oknu. Le-ta prikazuje ime datoteke, ki se trenutno arhivira ter procent
kon�anega dela. Za bolj nazorno predstavitev se procent kon�anega dela izrisuje
tudi grafi�no.
Slika 7.2.3: Napredek arhiviranja
Arhiviranje je možno med izvajanjem tudi preklicati, kar pa ne pomeni, da bo
arhivska datoteka neuporabna. Program bo samo prej zaklju�il z delom in izpisal
opozorilo, da vse datoteke niso bile arhivirane.
Dodatno vrednost predstavlja samodejno arhiviranje, ki ga je možno pognati ob
vnaprej dolo�enem �asu s pomo�jo Razporejevalnika opravil (sistemski program v
okolju Windows). Recimo, da želimo arhiviranje izvajati vsak dan ob 22:00. Najprej
moramo v lastnostih arhiviranja ozna�iti »Omogo�i samodejni zagon« in pod
»Oznaka za samodejni zagon« vpisati oznako, npr. dnevno. Nato v
Razporejevalniku opravil definiramo novo opravilo, ki zažene program vsak dan ob
22:00. Kot parameter ob zagonu programa podamo /a:dnevno.
Obnovitev podatkov iz arhiva: opravilo prekrije trenutne podatke s starejšo
razli�ico, zato moramo biti pri uporabi te izbire še posebej pazljivi. Priporo�amo
arhiviranje trenutnih podatkov in šele nato obnovitev.
Ob zagonu opravila moramo najprej izbrati arhivsko datoteko, iz katere bomo
obnavljali podatke. Za lažje iskanje so arhivske datoteke organizirane po letu in
Prakti�na uporaba algoritmov stiskanja podatkov 61
mesecu arhiviranja. Izbrati je možno samo eno arhivsko datoteko. Ciljno mapo
lahko pred pri�etkom obnovitve spremenimo, kar nam pride prav, �e želimo
podatke obnoviti v za�asno mapo, npr. da podatke najprej pregledamo. Za lažji
vnos uporabimo gumb »Prebrskaj«.
Slika 7.2.4: Obnovitev podatkov (izbira arhivske datoteke)
Ob potrditvi lahko napredek opazujemo v novem oknu. Napredek obnovitve
prikazuje ime datoteke, ki se trenutno obnavlja, ter procent kon�anega dela.
Obnovitev podatkov je možno med izvajanjem tudi preklicati. V tem primeru bodo
obnovljene samo datoteke do preklica.
Zapisovanje na medij CD/DVD: programi, ki omogo�ajo zapis na medije CD/DVD
so za ve�ino uporabnikov praviloma preve� zahtevni in jih zato ne uporabljajo.
Zato smo se odlo�ili, da postopek kar se da poenostavimo. Ob zagonu opravila
najprej izberemo vse arhivske datoteke, ki jih želimo zapisati na medij CD/DVD.
Za lažje iskanje so arhivske datoteke organizirane po letu in mesecu arhiviranja.
Prakti�na uporaba algoritmov stiskanja podatkov 62
Slika 7.2.5: Kopiranje na CD/DVD (izbira arhivske datoteke)
Preden za�nemo z zapisovanjem, moramo izbrati še osnovne nastavitve zapisa.
Program predlaga najbolj verjetne vrednosti, tako da v ve�ini primerov predlagane
vrednosti samo potrdimo:
• CD/DVD zapisovalnik izbiramo, �e jih je nameš�enih ve�. Program
predlaga prvega, ki ga najde.
• Ker je omogo�eno ve�kratno snemanje, lahko za vsako sejo zapisovanja
podamo drugo oznako. Oznaka je vidna v Raziskovalcu, ko vstavimo medij
CD/DVD v pogon. Ve�ina programov zna prikazati samo vsebino zadnje
seje zapisovanja. Privzeta oznaka se sestoji iz trenutnega datuma.
• Seznam arhivskih datotek smo pridobili z izbiro v prejšnjem koraku. Pred
zapisom imamo možnost, da katero od datotek izlo�imo, ne da bi morali
nazaj na izbiro.
• Statusna vrstica prikazuje opis ter grafi�ni prikaz napredka.
Prakti�na uporaba algoritmov stiskanja podatkov 63
Slika 7.2.6: Zapisovanje na medij CD/DVD (prikaz napredka)
Postopek zapisovanja je možno med izvajanjem tudi preklicati, vendar tega ne
priporo�amo, ker bo medij CD/DVD neuporaben. Razlog je v samem postopku
zapisovanja. Pred zapisovanjem se kreira binarna slika zapisa, na za�etku katere
se nahaja kazalo, ki mu sledijo datoteke. Slika se potem v enem kosu zapiše na
medij CD/DVD. �e postopek vmes prekinemo, bomo zapisali nepopolno kazalo ali
pa bo le-to kazalo na datoteke, ki niso bile zapisane. Tako bodo v najboljšem
primeru datoteke vidne v Raziskovalcu, vendar do njih ne bo možno dostopati.
7.3 Parametri za samodejni zagon
�e program poženemo brez parametrov, preidemo v interaktivni na�in, kjer
sami komuniciramo z uporabniškim vmesnikom: izbiramo vrsto opravila, ro�no
zaganjamo opravila itd. Program omogo�a tudi izvajanje v ozadju, brez
uporabniškega vmesnika. V ta namen moramo v ukazni vrstici podati stikala, ki
programu povedo, kaj naj stori. Stikalo mora biti podano v obliki /x:vrednost, kjer x
predstavlja oznako akcije. Možno je podati ve� stikal hkrati. Stikala, ki jih program
prepoznava so:
Prakti�na uporaba algoritmov stiskanja podatkov 64
• /d:ime dokumenta: naloži dokument s podanim imenom.
• /a:oznaka: zaženi vsa opravila arhiviranja s podano oznako.
• /p:oznaka: zaženi vse programe s podano oznako.
Ko so vsa samodejna opravila kon�ana, se program sam zapre.
Prakti�na uporaba algoritmov stiskanja podatkov 65
8 ZAKLJU�EK
Izdelava diplomskega dela nas je obogatila z mnogimi novimi znanji, saj je bilo
potrebno veliko raziskovalnega dela na razli�nih podro�jih. Zastavljeni cilj se je
izkazal za zelo interdisciplinarnega. V teoreti�nem delu diplomskega dela smo
tako obdelali nekatere kodirne tehnike, ra�unanje kode CRC, strukturo datotek ZIP
po predpisani specifikaciji ter vmesnike IMAPI za zapisovanje na medije CD/DVD.
Prakti�ni del diplomskega dela predstavlja program, s katerim smo teoreti�no
znanje povezali med sabo. Program omogo�a arhiviranje, obnovitev podatkov in
zapisovanje na medije CD/DVD. Da je program odziven tudi med izvajanjem
opravil, ki trajajo dalj �asa, npr. arhiviranje, smo morali vsa opravila napisati tako,
da izrabljajo mo� porazdeljenega izvajanja (angl. multithreaded execution).
Grafi�ni vmesnik temelji na novem Microsoftovem konceptu programiranja,
WPF (angl. Windows Presentation Foundation), ki je bil prvi� uporabljen pri
operacijskem sistemu Windows Vista. Glavna prednost WPF je, da popolnoma
lo�uje programsko logiko od predstavitvenega nivoja. V ta namen je nastal nov
deklarativni programski jezik XAML (angl. Extensible Application Markup
Language), s katerim definiramo izgled okna. Izgled se shrani v lo�eno datoteko s
kon�nico .xaml. Jezik ima tudi mo�no podporo za multimedijske vsebine in
vizualne u�inke, kar smo v programu izdatno izkoristili.
Program je nastal zaradi nenehnega povpraševanja uporabnikov, ki so želeli
enostavno rešitev za arhiviranje podatkov in zapis arhivskih datotek na medije
CD/DVD, ki bi služili kot varnostna kopija. Že pri na�rtovanju smo imeli v mislih
razli�ne izboljšave in dodatke, ki bi ga naredili še bolj uporabnega, zato je program
napisan modularno. Nakažimo nekaj izboljšav:
Prakti�na uporaba algoritmov stiskanja podatkov 66
• Arhivska datoteka trenutno ne podpira arhivov ve�jih od 4 GB. Razlog
ti�i v tem, da je odmik, na katerem se nahaja datoteka znotraj arhiva,
podan s štirimi zlogi (najve�ji odmik je tako 232 = 4 GB). Specifikacija
datoteke ZIP dolo�a dodatne strukture, kjer so vsa števila predstavljena
z osmimi zlogi (264). Program bi lahko uporabil te strukture ali pa težavo
rešil s segmentiranjem (razbitjem arhivske datoteke na ve� datotek).
• Podatkov v arhivski datoteki trenutno ni možno zaš�ititi z geslom.
Specifikacija datoteke ZIP predpisuje, kako je potrebno shraniti geslo in
kako kodirati podatke, �e je geslo podano. Program bi lahko ob uporabi
gesla samodejno kodiral podatke.
• Pri zapisovanju na pogon CD/DVD ni možno podati hitrosti zapisovanja.
Zaradi enostavnosti uporabe smo to opcijo izpustili, ker ve�ina
zapisovalnikov deluje brez napak tudi pri najvišji hitrosti. Problem bi
lahko nastopil pri starejših zapisovalnikih.
• Kadar se opravilo izvaja v ozadju preko Razporejevalnika opravil,
uporabnik ne vidi, ali je šlo kaj narobe. Program bi lahko poslal sporo�ilo
po elektronski pošti enemu ali ve� prejemnikom.
• Program bi lahko omogo�al, da se arhivske datoteke pošiljajo preko
interneta na strežnik. Postopek bi bilo možno avtomatizirati. V ta namen
bi na strežniku definirali spletno storitev, preko katere bi shranjevali
poslane datoteke. Opcija bi bila dostopna samo uporabnikom, ki bi
izrazili željo po takšnem arhiviranju.
• Ker stranke uporabljajo tudi naše druge programe, bi program lahko
omogo�al posodobitve programov, obveš�anje o novostih, popravkih itd.
V ta namen bi pridobival podatke od spletnega strežnika.
Prakti�na uporaba algoritmov stiskanja podatkov 67
LITERATURA
[1] D. Salomon, Data compression, The complete reference, 3. izd., Springer-
Verlag, New York, 2004
[2] P. Deutsch, RFC 1951: Deflate compressed data format specification,
Network Working Group, 1996
[3] A. Feldspar, An explanation of Deflate algorithm,
http://www.gzip.org/deflate.html
[4] Wikipedia, Deflate, http://en.wikipedia.org/wiki/DEFLATE
[5] PKWare Inc., .ZIP File Format Specification ver. 6.3.2, 1989-2007,
http://www.pkware.com/documents/casestudies/APPNOTE.TXT
[6] R. N. Williams, A painless guide to CRC error detection algorithms, ver. 3,
Rocksoft Pty Ltd, 1993
[7] Reliable Software, Cyclic Redundancy Check,
http://www.relisoft.com/Science/CrcMath.html
[8] Microsoft Visual Studio 2008 Documentation, Image Mastering API, Microsoft
Corp., 2007
[9] Standard ECMA-130: Data interchange on read-only 120mm optical data
disks (CD-ROM), 2. izd., 1996
[10] Standard ECMA-119: Volume and File Structure of CD-ROM for information
Interchange, 2. izd., 1998
[11] Microsoft Visual Studio 2008 Documentation, Windows Presentation
Foundation, Microsoft Corp., 2008
Prakti�na uporaba algoritmov stiskanja podatkov 68
PRILOGA A: Seznam slik
Slika 2.2.1: Algoritem LZ77 (prazen slovar) ................................................................................... 7
Slika 2.2.2: Algoritem LZ77 (prvi korak) ......................................................................................... 7
Slika 2.2.3: Algoritem LZ77 (po nekaj korakih) .............................................................................. 7
Slika 2.2.4: Algoritem LZ77 (nadaljevanje)..................................................................................... 8
Slika 2.2.5: Algoritem LZ77 (zadnji korak)...................................................................................... 8
Slika 2.3.1: Huffmanovo kodiranje (prvi korak) ............................................................................ 10
Slika 2.3.2: Huffmanovo kodiranje (drugi korak) .......................................................................... 10
Slika 2.3.3: Huffmanovo kodiranje (tretji korak) ........................................................................... 10
Slika 2.3.4: Huffmanovo kodiranje (�etrti korak) .......................................................................... 11
Slika 2.3.5: Huffmanovo kodiranje (peti korak) ............................................................................ 11
Slika 2.3.6: Huffmanovo kodiranje (šesti korak)........................................................................... 12
Slika 2.3.7: Huffmanovo kodiranje (sedmi korak)......................................................................... 12
Slika 2.3.8: Huffmanovo kodiranje (osmi korak)........................................................................... 12
Slika 2.3.9: Huffmanovo kodiranje (deveti korak)......................................................................... 13
Slika 2.3.10: Huffmanovo kodiranje (deseti korak)......................................................................... 13
Slika 2.3.11: Huffmanovo kodiranje (zadnji korak)......................................................................... 14
Slika 3.1: Algoritem Deflate (izboljšano iskanje v slovarju) ....................................................... 16
Slika 5.1: Primer seštevanja in odštevanja dveh števil v aritmetiki CRC .................................. 35
Slika 5.2: Primer množenja dveh števil v aritmetiki CRC .......................................................... 36
Slika 5.3: Primer deljenja dveh števil v aritmetiki CRC ............................................................. 37
Slika 7.1.1: Imenska podro�ja in razredi knjižnice DipZipClasses ............................................... 51
Slika 7.1.2: Razredni diagram (dokument) ................................................................................... 52
Slika 7.1.3: Razredni diagram (arhiviranje) .................................................................................. 53
Slika 7.1.4: Razredni diagram (zapisovanje na medij CD/DVD) .................................................. 56
Slika 7.2.1: Pozdravno okno programa ........................................................................................ 58
Slika 7.2.2: Okno z opravili za zagon programov......................................................................... 59
Slika 7.2.3: Napredek arhiviranja ................................................................................................. 60
Slika 7.2.4: Obnovitev podatkov (izbira arhivske datoteke) ......................................................... 61
Slika 7.2.5: Kopiranje na CD/DVD (izbira arhivske datoteke) ...................................................... 62
Slika 7.2.6: Zapisovanje na medij CD/DVD (prikaz napredka)..................................................... 63
Prakti�na uporaba algoritmov stiskanja podatkov 69
PRILOGA B: Seznam tabel
Tabela 2.3.1: Huffmanove kode za primer »Ra�unalnik ra�una « .................................................. 14
Tabela 3.1: Tabela Count[5] - število kod glede na njihovo dolžino............................................. 17
Tabela 3.2: Tabela NextCode[5] z za�etnimi kodami za posamezne dolžine.............................. 18
Tabela 3.3: Kanoni�ne Huffmanove kode .................................................................................... 18
Tabela 3.1.1: Kodna tabela za dolžine ujemanja ............................................................................ 20
Tabela 3.1.2: Huffmanove kode za literale/dolžine ujemanja.......................................................... 20
Tabela 3.1.3: Huffmanove kode za odmike ..................................................................................... 21
Tabela 3.2.1: Huffmanove kode in kanoni�ne Huffmanove kode za literale/dolžine....................... 25
Tabela 3.2.2: Huffmanove kode in kanoni�ne Huffmanove kode za zaporedje RLE...................... 26
Tabela 5.1: Tabela nekaterih standardnih deliteljev..................................................................... 38
Prakti�na uporaba algoritmov stiskanja podatkov 70
PRILOGA C: Vsebina zgoš�enke
Priložena zgoš�enka vsebuje besedilo diplome v obliki datoteke PDF: diploma.pdf.
V mapi »Program« se nahaja namestitveni paket za program DipZip, ki omogo�a
arhiviranje v datoteke ZIP. V mapi sta dve datoteki: DipZipSetup.msi in program
Setup.exe. Program DipZip namestimo z zagonom programa Setup.exe.
Uporabniki WinXP: pri zapisovanju na medije CD/DVD uporabljamo vmesnik
IMAPI 2.0, ki ni del operacijskega sistema WinXP, zato ga je potrebno posebej
namestiti. Namestitveni paket dobite na Microsoftovih straneh za podporo:
http://support.microsoft.com/kb/932716.
Uporabniki starejših razli�ic: za starejše razli�ice operacijskih sistemov
Windows vmesnik IMAPI 2.0 ni podprt.
top related