Daten archivieren mit zip, gzip und tar
Xin Wang
Inhaltsverzeichnis
1. Einführung
2. Komprimierungsmethoden von Zip und Gzip
2.1 LZ77
2.2 LZSS
2.3 LZH
Fazit
3. Funktionen der diversen Archivierungs- und Komprimierungsprogramme
3.1 allgemeine Informationen
3.2 spezifische Beschreibung
Winzip
Pkzip/Pkunzip
Zip/Unzip
Gzip
Tar
Tar und Gzip
3.3 Kompatibilität
3.4 Vergleich der Kompressionsrate
Literatur
Durch die heutige weltweite Vernetzung von Rechnern werden immer mehr
Daten übertragen. Um die begrenzte Leitungskapazität optimal zu
benutzen und hohe Übertragungsgeschwindigkeit zu erreichen, wurden
zahlreiche Kompressionsmethoden erfunden, die grob in zwei Gruppen
unterteilt werden können: verlustfreie Kompression und
verlustbehaftete Kompression.
Ein wichtiges Verfahren der verlustfreien Kompression ist das 1977 von
Abraham Lempel und Jakob Ziv erfundene Lempel-Ziv-Verfahren, auch LZ77
genannt. Viele bekannte Kompressionsprogramme, z.B. Zip oder Gzip,
basieren auf dem Verfahren.
Diese Ausarbeitung handelt von den wichtigen Komprimierungsprogrammen
Zip, Gzip und dem Archivierungsprogramm Tar. Im Folgenden werden der
Komprimierungsalgorithmus LZ77 sowie dessen Erweiterung LZSS, LZH
ausführlich erklärt. Anschließend werden die interessantesten
Funktionen von unterschiedlichen Programmen wie Winzip, Zip, Pkzip,
Gzip, Tar erklärt.
Das Packprogramm Gzip ist eine bekannte Implementierung des
LZ77-Verfahrens, dessen Erweiterung, das LZH-Verfahren, bei der
Komprimierung mit Winzip angewendet wird. Die Funktionsweise der
Kompressionsverfahren wird nachfolgend anhand von Beispielen
vorgestellt.
Idee
Der LZ77 Algorithmus basiert auf Verzeichnissen aus
Strings. Kommt ein String mehrmals vor, so wird er nicht zweimal
gespeichert, sondern durch einen Zeiger auf den schon vorhandenen
ersetzt.
Struktur
LZ77 war das erste vorgestellte tabellengesteuerte
Komprimierungsverfahren. Die Datenstruktur besteht aus zwei Teilen:
Suchpuffer und Vorschaupuffer. Während in dem Suchpuffer die schon
kodierten Zeichen stehen, zeigt der Vorschaupuffer auf die als
nächstes zu kodierenden Zeichen.
Beispiel
- In dieser Ausarbeitung wird angenommen, dass pro Zeichen 1 Byte
Speicherplatz benötigt wird.
- maximale Suchpufferlänge: 20 Bytes
- maximale Vorschaupufferlänge: 10 Bytes
- der zu kodierende Satz lautet: EINE_MAUS_BAUT_EIN_HAUS.
|
Nr.
|
Suchpuffer
|
Vorschaupuffer
|
Kodierung
|
| 1 |
|
EINE_MAUS_ |
( 0, 0, "E" ) |
| 2 |
E
|
INE_MAUS_B |
( 0, 0, "I" ) |
| 3 |
EI
|
NE_MAUS_BA |
(0, 0, "N" ) |
| 4 |
EIN
|
E_MAUS_BAU |
(3, 1, "_" ) |
| 5 |
EINE_
|
MAUS_BAUT_ |
(0, 0, "M" ) |
| 6 |
EINE_M
|
AUS_BAUT_E |
(0, 0, "A" ) |
| 7 |
EINE_MA
|
US_BAUT_EI |
(0, 0, "U" ) |
| 8 |
EINE_MAU
|
S_BAUT_EIN |
(0, 0, "S" ) |
| 9 |
EINE_MAUS
|
_BAUT_EIN_ |
(5, 1, "B" ) |
| 10 |
EINE_MAUS_B
|
AUT_EIN_HA |
(5, 2, "T" ) |
| 11 |
EINE_MAUS_BAUT
|
_EIN_HAUS. |
(5, 1, "E" ) |
| 12 |
EINE_MAUS_BAUT_E
|
IN_HAUS. |
(15, 2, "_" ) |
| 13 |
EINE_MAUS_BAUT_EIN_
|
HAUS. |
(0, 0, "H" ) |
| 14 |
EINE_MAUS_BAUT_EIN_H
|
AUS. |
(14, 3, "." ) |
| 15 |
_MAUS_BAUT_EIN_HAUS.
|
|
|
Algorithmus und Erklärung des Beispiels
- Am Anfang ist der Suchpuffer leer, der Vorschaupuffer hat eine
konstante Größe.
- Wir nehmen das erste Zeichen aus dem Vorschaupuffer, und
durchsuchen den Suchpuffer danach von rechts nach links.
- Siehe Bsp. Zeile 1-3, 5-8 oder 13: Wird es im Suchpuffer nicht
gefunden, kodieren wir das Zeichen mit (0,0, "Zeichen").
- Siehe Bsp. Zeile 14: Wird es gefunden ("a" von "baut"), dann
nehmen wir das nächste Zeichen ("u") aus dem Vorschaupuffer und suchen
nach der Kombination ("au") im Suchpuffer weiter nach links
fortschreitend, aber nicht erneut von rechts beginnend ("au" von
"baut").
- Wir fahren damit fort, bis kein passendes Muster mehr gefunden
wird ("aus" bei "Maus").
- Wir kodieren den gefundenen String durch ein 3-er Tupel (Offset,
Länge des Strings, nächstes Zeichen), im Beispiel (14, 3, "."). Der
Offset zeigt die Position des Musters im Suchpuffer.
- Wir verschieben beide Puffer um (Stringlänge + 1) Zeichen nach
rechts und wiederholen den Vorgang 2, bis das Ende der zu
komprimierenden Daten erreicht wird.
Wichtige Bemerkungen
- Das Muster, das im Suchpuffer gesucht wird, kann in den
Vorschaupuffer "hineinlaufen".
- Sei L die maximale Länge des Vorschaupuffers, dann ist die
maximale Länge des gefundenen Strings L-1.
|
Suchpuffer
|
Vorschaupuffer
|
Kodierung
|
|
Die Katze ruft miau
|
miaumiaumiau |
( 4, 11, "u" ) |
- Die Kompressionsrate hängt von der maximalen Länge des
Suchpuffers, des Vorschaupuffers und der Entropie des Quelltextes
(bezüglich LZ77) ab.
- Vergrößerung der Länge des Suchpuffers (bzw. des Vorschau-Puffers)
bringt mit größerer Wahrscheinlichkeit mehr Treffer, aber auch höheren
Aufwand.
- Bei ähnlichen nah beieinander liegenden Textsequenzen bekommt man
eine hohe Komprimierung.
Dekomprimierung
Die Dekomprimierung ist nicht kompliziert und wird hier nicht
ausführlich erklärt. Es fällt jedoch auf, dass man bei der
Dekomprimierung weder die Suchpuffer-, noch die Vorschaupufferlänge
kennen muss.
Eine bekannte Erweiterung von LZ77 ist der von James Storer und Thomas
Szymanski 1982 entwickelte LZSS-Algorithmus.
Änderungen zu LZ77
- Der Suchpuffer ist in der Form eines Binärsuchbaumes gegeben.
- Wenn die Länge einer Zeichenfolge kürzer als die minimale Länge
ist, wird die Zeichenfolge an sich als Code ausgegeben. Die minimale
Länge ist dabei die Länge, die eine Zeichenfolge haben muss, um
kodiert zu werden.
- Die Zeichenfolgen werden nicht von einem 3-er Tupel, sondern von
einem 2-er Tupel (Offset, Länge) kodiert.
Bemerkung:
Der Suchpuffer enthält im allgemeinen maximal 65535 Zeichen, und der
Vorschaupuffer 255 Zeichen, also besitzt das 2-er Tupel (Offset,
Länge) im Speicher 3 Bytes, daher ist die minimale zu kodierende Länge
3 Bytes.
Beispiel
- maximale Suchpufferlänge: 15 Bytes.
- maximale Vorschaupufferlänge: 5 Bytes.
|
Suchpuffer
|
Vorschaupuffer
|
weiterer Text
|
|
ein_Kind_grüßt_
|
ein_a |
nderes_Kind |
Wörter des Suchbaumes:
|
Wort
|
Offset
|
Wort
|
Offset
|
|
ein_K
|
15
|
_grüß
|
7
|
|
in_Ki
|
14
|
grüßt
|
6
|
|
n_Kin
|
13
|
rüßt_
|
5
|
|
_Kind
|
12
|
üßt_e
|
4
|
|
Kind_
|
11
|
ßt_ei
|
3
|
|
ind_g
|
10
|
t_ein
|
2
|
|
nd_gr
|
9
|
_ein_
|
1
|
|
d_grü
|
8
|
|
|
Der Binärsuchbaum in lexikalischer Ordnung ergibt sich wie folgt:
Erklärung:
- Der Binärsuchbaum hat maximal 15 Wörter und jedes Wort enthält 5
Zeichen. Der Suchbaum soll ausbalanciert sein. Das bedeutet, dass zu
jedem Knoten des Suchbaumes die Höhendifferenz seines linken und
rechten Teilbaumes nicht größer als eins ist. In diesem Fall ist der
Aufwand beim Suchen einer übereinstimmenden Zeichenfolge O(log n),
wobei n die Länge des Suchpuffers ist.
- Kodierung von "ein_a" : (15, 4) (Offset = 15, Länge = 4)
- Die beiden Puffer werden um 4 Zeichen nach rechts verschoben. Die
Wörter "ein_K", "in_Ki", "n_Kin", und "_Kind" werden aus dem Suchbaum
entfernt, während die "ein_a", "in_an", "n_and", "_ande", "ander" neu
hinzugefügt. Der Suchbaum muss im Allgemeinen umsortiert werden, damit
er ausbalanciert ist.
Dekodierung
Im Ausgabestring müssen wir außer der komprimierten Daten auch
zusätzliche Informationen angeben, um bei der Dekomprimierung
festzustellen, ob das aktuelle Zeichen als Zeiger oder Wert
interpretiert werden soll.
Die Informationen sind:
- die Anzahl der Durchläufe. Jedes Mal wenn wir entweder einen
Zeiger oder ein einzelnes unkomprimiertes Zeichen in die Ausgabe
schreiben, zählen wir dies als einen Durchlauf.
- die Größe des Bitfeldes.
- das Bitfeld. Wir speichern in einem Bitfeld, ob wir im
entsprechenden Durchlauf einen Zeiger oder ein einzelnes Zeichen
gespeichert haben. Angenommen, wir haben 10 Durchläufe, dann gibt es
10 Bits in unserem Bitfeld. Wir schreiben eine Eins in ein Bitfeld,
wenn in dem Durchlauf ein Zeiger gespeichert wird, sonst schreiben wir
eine Null hinein.
Am Anfang der Ausgabe, im Header, speichern wir nun diese
Informationen. Die ersten 8 Byte sind für die Anzahl der Durchläufe
und für die Größe des Bitfeldes reserviert (jeweils 4 Byte). Dann
kommt das Bitfeld, das in Bytes umgewandelt wurde, und zuletzt die
komprimierten Daten.
Der LZSS-Algorithmus ist eine Verbesserung von LZ77, eine weitere
Optimierung von LZSS erreicht man, indem seine Ausgabe mit Hilfe
anderer Kompressionsverfahren nochmals verdichtet wird. Der
Lempel-Ziv-Huffman Algorithmus ist eine bekannte Implementierung
davon. Er kodiert das LZSS-Modell mit dem adaptiven Huffman, um eine
noch bessere Kompressionsrate zu erreichen. Das LZH-Verfahren wird bei
Komprimierung von Winzip angewendet.
Um einen Überblick zu bekommen, fassen wir nun die Beziehung der
Kompressionsmethoden von diversen Packprogrammen durch folgende Grafik
zusammen.
Für die Forschung und weitere Entwicklung sind die
Kompressionsalgorithmen zwar ganz interessant und faszinierend, aus
der Perspektive der Anwender hingegen sind die unterschiedliche
Funktionen, die von zahlreichen Packprogrammen angeboten werden,
wichtiger. Im Folgenden werden sie im Vergleich auszugsweise
erläutert.
|
Programme
|
Haupfunktion
|
Hauptsystemumgebung
|
Endung
|
|
Winzip
|
Dateien komprimieren und archivieren
|
Windows
|
.zip
|
|
Pkzip
|
Dateien komprimieren und archivieren
|
Dos
|
.zip
|
|
Zip
|
Dateien komprimieren und archivieren
|
Unix
|
.zip
|
|
Gzip
|
einzelne Datei komprimieren
|
Unix
|
.gz
|
|
Tar
|
Dateien archivieren (nicht komprimieren)
|
Unix
|
.tar
|
|
Tar und Gzip
|
Dateien archivieren und komprimieren
|
Unix
|
.tar.gz, .tgz
|
Bemerkung
Unter "Daten archivieren" versteht man, dass aus mehreren Dateien,
ohne sie zu komprimieren, eine einzige Datei erzeugt wird. Aber das
reine Archivierungsprogramm, wie Tar, spielt keine großartige Rolle
bei Datenübertragung, viel sinnvoller ist seine Verbindung mit einem
Komprimierungsprogramm, z.B. Gzip, womit man das Archiv verkleinern
kann.
Winzip ist heutzutage das populärste Kompressionsprogramm unter
Windows. Es ist beliebt wegen seiner leicht zu bedienenden Oberfläche
und guter Kompatibilität zu den anderen Packprogrammen. Mit Winzip
kann man ein ziemlich gutes Kompressionsergebnis von Textdateien
erreichen.
Wie man mit Winzip arbeitet, kennt fast jeder. Die Erklärung wird hier
vernachlässigt.
Im Folgenden wollen wir durch Versuche eine interessante
Verhaltensweise von Winzip zeigen.
Es wird eine Datei "Text1.doc" 3 mal kopiert und mit den 3 Kopien
zusammen in ein Archiv hinzugefügt. Folgende Tabelle zeigt die
Kompressionsergebnisse von Winzip und Winrar (unter der
Solid-Funktion).
|
Archiv
|
Name
|
Datum
|
Größe
|
Komprimierung
|
Komprimierte Größe
|
|
Winzip
|
versuch.zip 114 KB
|
Text4.txt
|
07.11.2001
|
271.274
|
89.29%
|
29.054
|
|
Text3.txt
|
07.11.2001
|
271.274
|
89.29%
|
29.054
|
|
Text2.txt
|
07.11.2001
|
271.274
|
89.29%
|
29.054
|
|
Text1.txt
|
07.11.2001
|
271.274
|
89.29%
|
29.054
|
|
Winrar
|
versuch.rar 18 KB
|
Text4.txt
|
07.11.2001
|
271.274
|
93,50%
|
17.626
|
|
Text3.txt
|
07.11.2001
|
271.274
|
99.93%
|
170
|
|
Text2.txt
|
07.11.2001
|
271.274
|
99.94%
|
164
|
|
Text1.txt
|
07.11.2001
|
271.274
|
99.94%
|
167
|
Schlussfolgerungen
Wie man leicht erkennen kann, komprimiert Winzip die Dateien und fügt
sie dem Archiv einfach hinzu. Winrar nutzt unter Verwendung der
Solid-Funktion Ähnlichkeiten zwischen den Dateien aus. Aus diesem
Grund wird hier nur eine Datei vollständig komprimiert, die anderen
Komprimierungen bestehen aus Verweisen zu dieser Datei. In einem
darauffolgenden Versuch wurde eine der Textdateien in der Mitte
geändert, indem eine kurze Textsequenz hinzugefügt wurde, doch
trotzdem war sie in komprimierter Form kaum größer als vorher. Das
Solid-Verfahren ist laut Winrar sinnvoll für kleinere Dateien, die
sich ähneln.
Pkzip ist der mit Abstand schnellste Packer. Mit seiner guten Leistung
gehört er zu den verbreitetsten Kompressionsprogrammen.
Pkzip hat drei Modi: Pkzip (Packer), Pkunzip (Entpacker), Zip2exe
(Selbstextrahierer). Seine Anwendung unter DOS ist sehr einfach.
Im Folgenden wird sie anhand von Beispielen gezeigt.
- Ziel: Dateien (text1.txt, text2.doc) in ein Archiv(versuch.zip)
packen
- Syntax: pkzip [optionen] <Archivname> <Dateiname>
- Befehl: pkzip versuch.zip text1.txt text2.doc
- Ziel:das ganze Archiv(versuch.zip) entpacken:
- Syntax: pkunzip [optionen] <Archivname>
- Befehl: pkunzip versuch.zip
- Ziel: Nur text1.txt aus dem Archiv (versuch.zip) entpacken
- Syntax: pkunzip [optionen] <Archivname> <Dateiname>
- Befehl: pkunzip versuch.zip text1.txt
Mit den verschiedenen Parametern, die jeweils durch einen Bindestrich
eingeleitet werden, kann man die Grundfunktionen durch Optionen
modifizieren.
Genaue Informationen erhält man durch Eingabe des Kommandos pkzip oder pkunzip.
Zip ist ein Packer unter Unix. Unzip ist der entsprechende Entpacker.
Zip/Unzip haben ähnliche Syntax und Funktionen wie Pkzip/Pkunzip. Zu
beachten sind die folgenden Besonderheiten.
- Befehl: zip -k versuch.zip text1.txt text2.doc
- Erklärung: Mit dem Parameter "k" kann man ein Archiv erzeugen, das
der Pkzip-Format entspricht, d.h., dass man mit Pkunzip das Archiv
entpacken kann.
- Mit Unzip kann man problemlos das mit Pkzip gepackte Archiv entpacken.
Gzip ist das häufig benutzte Kompressionsprogramm unter Unix. Es
erzielt eine erheblich bessere Kompressionsrate als compress. Für das
Entpacken ist Gunzip zuständig. Im Gegensatz zu den anderen
Packprogrammen komprimiert Gzip nur die einzelnen Dateien. Nach der
Komprimierung werden die originalen Dateien durch die Gzip-Dateien
ersetzt. Die Anwendung wird durch folgendes Beispiel erklärt.
- Ziel: eine Datei (text1.txt) packen.
- Syntax: gzip <Dateiname>
- Befehl: gzip text1.txt
- Ziel: die gepackte Datei (text1.gz) entpacken
- Syntax: gzip -d <Dateiname> oder gunzip <Dateiname>
- Befehl: gzip -d text1.txt.gz oder gunzip text1.txt.gz
- Ziel: eine komprimierte Text-Datei lesen
- Syntax: zcat <Dateiname>
- Befehl: zcat text1.txt.gz
- Ziel: eine defekte komprimierte Datei bis zur Fehlerstelle
retten/entpacken
- Syntax: zcat <Datei 1> > <Datei 2>
- Befehl: zcat text1.txt > text.txt
Unter dem Kommando gzip -h kann man die weitere Hilfe erhalten.
Tar ist das Standard-Werkzeug zum Archivieren von Dateien unter
Unix. Mit Tar werden die einzelnen Dateien oder Inhalte eines
Verzeichnisses oder Verzeichnisse in einer Datei abgelegt. Aber die
Archive werden mit tar nicht komprimiert.
Tar besitzt drei Modi: Archivieren, Entarchivieren und Inhalt
anzeigen. Den Modus wählt man mit einer der folgenden Optionen aus:
- c (create): Erzeugen einer tar- Datei
- x (extract): Entpacken einer tar- Datei
- t (table of content): den Inhalt einer tar-Datei anzeigen, ohne
sie zu entpacken.
Tar wurde früher vor allem zur Datensicherung auf Magnetbändern
eingesetzt. Wenn man das Archiv in einer Datei speichern oder eine
Archivdatei entpacken will, muss man die Option f (file) verwenden und
den Dateinamen angeben, sonst würde auf das Bandlaufwerk zugriffen
werden, welches nur in den seltensten Fällen vorhanden bzw. zugänglich
ist.
Mit Option v (verbose) kann man während der Bearbeitung die aktuelle
Information über den Zustand der Archivierung erhalten.
Im Folgenden wird die Syntax anhand von Beispielen erklärt.
- Ziel: aus den Dateien ein Archiv erzeugen
- Syntax: tar cvf <Archivname> <Dateiname
1>... <Dateinamen>
- Befehl: tar cvf versuch.tar text1.txt text2.doc text3.txt
- Ziel: ein erstelltes Archiv nachträglich erweitern
- Syntax: tar rvf <Archivname> <Dateiname
1>...<Dateinamen1>
- Befehl: tar rvf versuch.tar text1.txt text2.doc
- Ziel: ein ganzes Archiv entpacken
- Syntax: tar xvf <Archivname>
- Befehl: tar xvf versuch.tar
- Ziel: Dateien aus einem Archiv entpacken
- Syntax: tar xvf <Archivname> <Datei 1>...<Datei x>
- Befehl: tar xvf versuch.tar text2.doc text3.txt
- Ziel: den Inhalt einer tar-Datei anzeigen
- Syntax: tar tvf <Archivname>
- Befehl: tar tvf versuch.tar
Weitere Hilfe kriegt man durch Eingabe des Kommandos: tar -h
Wenn man eine tar-Datei mit dem Texteditor öffnet, dann kann man
leicht erkennen, dass Tar bei der Archivierung Trennlinien benutzt.
Unter Unix kann man feststellen, wenn die zu archivierenden Dateien
insgesamt kleiner als 10240 Bytes sind, werden sie durch Trennlinien
und Ergänzungen immer auf diese Größe gebracht.
Tar ist ein reines Archivierungsprogramm, zur Komprimierung der
Archive muss man sie mit einem Komprimierungsprogramm packen.
Dazu dient z.B. das Programm compress, oder das noch leistungsfähigere
GNU-Programm gzip.
Im Folgenden werden wir hauptsächlich die Kopplung von tar und gzip
kennenlernen.
- Ziel: ein Archiv mit gzip komprimieren
- Beispiel: gzip versuch.tar
- Ziel: ein Archiv mit gzip/gunzip dekomprimieren
- Beispiel: gunzip versuch.tar.gz oder gzip -d
versuch.tar.gz
- Die GNU Version von tar, die man meistens als gtar aufrufen kann, kann auch gleich gzip aufrufen und das tar Archiv komprimieren.
- Ziel: Dateien mit tar archivieren und gleichzeitig mit gzip komprimieren
- Syntax: gtar cvfz <Archivname> <Dateiname
1>...<Dateiname n>
- Beispiel: gtar cvfz versuch.tar text1.txt text2.doc text3.txt
- Bemerkung: Die Komprimierung wird durch die z Option
eingeschaltet. Die Dateiendung dazu lautet ".tgz" oder ".tar.gz".
- Ziel: Dateien mit gzip dekomprimieren und mit tar entpacken
- Syntax: gtar xvfz <Archivname>
- Beispiel: gtar xvfz versuch.tgz
- Bemerkung: Die Dekomprimierung wird auch durch die z Option eingeschaltet.
Im Folgenden wird die Kompatibilität von diversen
Komprimierungsprogrammen durch eine Grafik dargestellt.
Erklärung:
Es wurde eine Text-Datei (2.267 KB) mit den vier oben genannten
Komprimierungsprogrammen jeweils in schnellste, mittlere, und beste
Kompressionsrate komprimiert. Zu beachten ist, dass dies ein
Versuchsergebnis und kein repräsentativer Test ist, da man hierzu viel
größere Datenmengen untersuchen müsste und auch berücksichtigen
müsste, dass sich die Algorithmen bei unterschiedlichen Dateiarten
unterschiedlich verhalten.
Der Versuch zeigt uns trotzdem, dass die Leistungen bei der
Kompression sehr ähnlich sind. Für welches Programm man sich
entscheidet, hängt hauptsächlich von der Benutzerfreundlichkeit und
dem verwendeten Betriebssystem ab.
|
Letzte Änderung: 2002-06-13 10:45:25
|