Załóżmy, że mam 10 000 plików XML. Załóżmy teraz, że chcę wysłać je do przyjaciela. Przed wysłaniem chciałbym je skompresować.
Metoda 1: Nie kompresuj ich
Wyniki:
Resulting Size: 62 MB
Percent of initial size: 100%
Metoda 2: Spakuj każdy plik i wyślij mu 10 000 plików XML
Komenda:
for x in $(ls -1) ; do echo $x ; zip "$x.zip" $x ; done
Wyniki:
Resulting Size: 13 MB
Percent of initial size: 20%
Metoda 3: Utwórz pojedynczy plik zip zawierający 10 000 plików xml
Komenda:
zip all.zip $(ls -1)
Wyniki:
Resulting Size: 12 MB
Percent of initial size: 19%
Metoda 4: Połącz pliki w jeden plik i skompresuj go
Komenda:
cat *.xml > oneFile.txt ; zip oneFile.zip oneFile.txt
Wyniki:
Resulting Size: 2 MB
Percent of initial size: 3%
Pytania:
- Dlaczego otrzymuję tak radykalnie lepsze wyniki, gdy tylko kompresuję pojedynczy plik?
- Spodziewałem się radykalnie lepszych wyników przy użyciu metody 3 niż metody 2, ale nie. Dlaczego?
- Czy to zachowanie jest specyficzne
zip
? Jeśli spróbuję użyć,gzip
czy uzyskam inne wyniki?
Dodatkowe informacje:
$ zip --version
Copyright (c) 1990-2008 Info-ZIP - Type 'zip "-L"' for software license.
This is Zip 3.0 (July 5th 2008), by Info-ZIP.
Currently maintained by E. Gordon. Please send bug reports to
the authors using the web page at www.info-zip.org; see README for details.
Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip,
as of above date; see http://www.info-zip.org/ for other sites.
Compiled with gcc 4.4.4 20100525 (Red Hat 4.4.4-5) for Unix (Linux ELF) on Nov 11 2010.
Zip special compilation options:
USE_EF_UT_TIME (store Universal Time)
SYMLINK_SUPPORT (symbolic links supported)
LARGE_FILE_SUPPORT (can read and write large files on file system)
ZIP64_SUPPORT (use Zip64 to store large files in archives)
UNICODE_SUPPORT (store and read UTF-8 Unicode paths)
STORE_UNIX_UIDs_GIDs (store UID/GID sizes/values using new extra field)
UIDGID_NOT_16BIT (old Unix 16-bit UID/GID extra field not used)
[encryption, version 2.91 of 05 Jan 2007] (modified for Zip 3)
Edycja: metadane
Jedna odpowiedź sugeruje, że różnicą są metadane systemowe przechowywane w pliku zip. Nie sądzę, że może tak być. Aby przetestować, wykonałem następujące czynności:
for x in $(seq 10000) ; do touch $x ; done
zip allZip $(ls -1)
Otrzymany zip ma 1,4 MB. Oznacza to, że nadal jest ~ 10 MB niewyjaśnionego miejsca.
.tar.gz
a nie tylko spakowanie całego katalogu.$(ls -1)
, wystarczy użyć*
:for x in *
;zip all.zip *
Odpowiedzi:
Podczas kompresji Zip traktuje zawartość każdego pliku osobno. Każdy plik będzie miał swój własny skompresowany strumień. Algorytm kompresji obsługuje (zwykle DEFLATE ) w celu identyfikacji powtarzających się odcinków. Jednak nie ma wsparcia w Zip, aby znaleźć redundancję między plikami.
Dlatego jest tak dużo dodatkowego miejsca, gdy zawartość jest w wielu plikach: umieszcza ten sam skompresowany strumień w pliku wiele razy.
źródło
there is no support in Zip to find redundancy between files
jest to specyfikacja pliku zip?Kompresja ZIP opiera się na powtarzalnych wzorcach w danych, które mają być kompresowane, a kompresja staje się lepsza, im dłuższy jest plik, ponieważ coraz więcej wzorów można znaleźć i używać.
Uproszczone, jeśli skompresujesz jeden plik, słownik odwzorowujący (krótkie) kody na (dłuższe) wzory jest koniecznie zawarty w każdym wynikowym pliku zip; jeśli skompresujesz jeden długi plik, słownik zostanie „ponownie użyty” i stanie się jeszcze bardziej skuteczny we wszystkich treściach.
Jeśli twoje pliki są nawet trochę podobne (jak zawsze tekst), ponowne użycie „słownika” staje się bardzo wydajne, a wynikiem jest znacznie mniejszy całkowity zip.
źródło
W Zip każdy plik jest kompresowany osobno. Przeciwieństwem jest „solidna kompresja”, tzn. Pliki są kompresowane razem. 7-zip i Rar domyślnie używają solidnej kompresji. Gzip i Bzip2 nie mogą kompresować wielu plików, więc najpierw używany jest Tar, co daje taki sam efekt jak solidna kompresja.
Ponieważ plik xml ma podobną strukturę i prawdopodobnie podobną zawartość, jeśli pliki zostaną skompresowane razem, kompresja będzie wyższa.
Na przykład, jeśli plik zawiera ciąg,
"<content><element name="
a kompresor już znalazł ten ciąg w innym pliku, zastąpi go małym wskaźnikiem do poprzedniego dopasowania, jeśli kompresor nie używa „stałej kompresji”, pierwsza częstotliwość łańcucha w plik zostanie nagrany jako literał, który jest większy.źródło
Zip nie tylko przechowuje zawartość pliku, ale także przechowuje metadane pliku, takie jak identyfikator użytkownika będącego właścicielem, uprawnienia, czasy tworzenia i modyfikacji itd. Jeśli masz jeden plik, masz jeden zestaw metadanych; jeśli masz 10 000 plików, masz 10 000 zestawów metadanych.
źródło
Opcją pominiętą przez OP jest skompresowanie wszystkich plików razem z wyłączoną kompresją, a następnie skompresowanie wynikowego zipu z kompresją ustawioną na maksimum. To z grubsza emuluje zachowanie skompresowanych archiwów * nix .tar.Z, .tar.gz, .tar.bz itp., Umożliwiając kompresji wykorzystanie nadmiarowości między granicami plików (czego algorytm ZIP nie może wykonać, gdy jest uruchomiony w jednym przechodzić). Pozwala to później wyodrębnić poszczególne pliki XML, ale maksymalizuje kompresję. Minusem jest to, że proces wyodrębniania wymaga dodatkowego kroku, tymczasowo zajmując znacznie więcej miejsca na dysku niż byłoby to potrzebne w przypadku zwykłego pliku .zip.
Dzięki wszechobecności bezpłatnych narzędzi, takich jak 7-Zip do rozszerzenia rodziny tar na Windows, naprawdę nie ma powodu, aby nie używać .tar.gz lub .tar.bz itp., Ponieważ Linux, OS X i BSD mają natywne narzędzia do manipulowania nimi.
źródło
xz
/ 7-zip). W każdym razie adaptacyjne słowniki mogą wykrywać wzory, gdy są widoczne. To nie tak, że po prostu buduje system kodowania statycznego oparty na pierwszych 32k. Właśnie dlatego gzip nie jest do kitu.Format kompresji zip przechowuje i kompresuje każdy plik osobno. Nie korzysta z powtarzania między plikami, tylko w obrębie pliku.
Łączenie pliku pozwala zipowi na skorzystanie z powtórzeń we wszystkich plikach, co powoduje znacznie większą kompresję.
Powiedzmy na przykład, że każdy plik XML ma określony nagłówek. Nagłówek występuje tylko raz w każdym pliku, ale jest powtarzany prawie identycznie w wielu innych plikach. W metodach 2 i 3 zip nie mógł tego skompresować, ale w metodzie 4 mógł.
źródło
Obok metadanych wspomnianych przez Mike'a Scotta w algorytmie kompresji występuje również narzut.
Podczas kompresji kilku pojedynczych małych plików musisz mieć dużo szczęścia, aby móc je skompresować, tak aby wypełnić jeden blok kompresji. Podczas kompresji pojedynczego bloku monolitycznego system może po prostu kontynuować przesyłanie strumieniowe danych do algorytmu, ignorując „granice” (z powodu braku lepszego słowa) poszczególnych plików.
Wiadomo również, że ASCII ma wysoki współczynnik kompresji. Ponadto XML jest często bardzo powtarzalny, co sprawia, że metadane stanowią dużą część danych, których nie można tak łatwo skompresować jak zawartość XML.
Wreszcie, jeśli pamięć działa poprawnie, zip używa kodowania słownikowego, co jest szczególnie skuteczne w plikach ascii, a tym bardziej w XML ze względu na ich powtarzalność
Wyjaśnienie kompresji danych: http://mattmahoney.net/dc/dce.html
źródło
Rozważ to XML:
XML ma bardzo powtarzalną strukturę, Zip korzysta z tych powtórzeń, aby zbudować słownik, w którym wzorzec ma więcej wystąpień, a następnie, podczas kompresji, używa mniej bitów do przechowywania większej liczby powtarzających się wzorów, a więcej bitów do przechowywania mniej powtarzanych wzorów .
Gdy połączysz te pliki, plik źródłowy (źródło zip) jest duży, ale zawiera znacznie więcej powtarzających się wzorców, ponieważ dystrybucja nudnych struktur XML jest amortyzowana w dużym całym pliku, dając szansę ZIPowi na przechowanie tych wzorów używając mniej bitów.
Teraz, jeśli połączysz różne XML w jeden plik, nawet jeśli pliki te mają zupełnie inne nazwy znaczników, algorytm kompresji znajdzie najlepszą dystrybucję wzorców we wszystkich plikach, a nie plik po pliku.
Ostatecznie algorytm kompresji znalazł najlepszy powtarzalny rozkład wzorca.
źródło
Oprócz odpowiedzi na 7-Zip istnieje jeszcze jedno podejście, które nie jest tak dobre, ale byłoby warte przetestowania, jeśli z jakiegoś powodu nie chcesz używać 7-Zip:
Skompresuj plik zip. Teraz zwykle plik zip jest nieściśliwy, ale gdy zawiera wiele identycznych plików, kompresor może znaleźć tę nadmiarowość i skompresować ją. Zauważ, że zauważyłem również niewielki zysk w przypadku dużej liczby plików bez redundancji. Jeśli naprawdę zależy Ci na rozmiarze, warto wypróbować, jeśli masz w archiwum bardzo dużo plików.
źródło