Mengapa Zip dapat mengkompres satu file lebih kecil dari banyak file dengan konten yang sama?

126

Misalkan saya memiliki 10.000 file XML. Sekarang anggaplah saya ingin mengirim mereka ke teman. Sebelum mengirim mereka, saya ingin mengompres mereka.

Metode 1: Jangan kompres

Hasil:

Resulting Size: 62 MB
Percent of initial size: 100%

Metode 2: Zip setiap file dan kirim 10.000 file xml

Perintah:

for x in $(ls -1) ;  do   echo $x ; zip "$x.zip" $x ; done

Hasil:

Resulting Size: 13 MB
Percent of initial size: 20%

Metode 3: Buat zip tunggal yang berisi 10.000 file xml

Perintah:

zip all.zip $(ls -1)

Hasil:

Resulting Size: 12 MB
Percent of initial size: 19%

Metode 4: Menggabungkan file menjadi satu file & zip itu

Perintah:

cat *.xml > oneFile.txt ; zip oneFile.zip oneFile.txt

Hasil:

Resulting Size: 2 MB
Percent of initial size: 3%

Pertanyaan:

  • Mengapa saya mendapatkan hasil yang jauh lebih baik ketika saya hanya zip file tunggal?
  • Saya berharap mendapatkan hasil yang lebih baik secara drastis menggunakan metode 3 daripada metode 2, tetapi tidak. Mengapa?
  • Apakah perilaku ini khusus untuk zip? Jika saya mencoba menggunakan gzipapakah saya akan mendapatkan hasil yang berbeda?

Informasi tambahan:

$ 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)

Edit: Data meta

Satu jawaban menunjukkan bahwa perbedaannya adalah data meta sistem yang disimpan di zip. Saya tidak berpikir ini bisa terjadi. Untuk menguji, saya melakukan hal berikut:

for x in $(seq 10000) ; do touch $x ; done
zip allZip $(ls -1)

Zip yang dihasilkan adalah 1.4MB. Ini berarti masih ada ~ 10 MB ruang yang tidak dapat dijelaskan.

sixtyfootersdude
sumber
34
Jika saya tidak salah, ini adalah phenomona yang menyebabkan orang membuat .tar.gzbukan hanya zip seluruh direktori.
corsiKa
18
Sebuah pertanyaan serupa sudah bertanya, tl; dr menggunakan arsip 7zip padat.
Dmitry Grigoryev
3
@sixtyfootersdude Sebagai tes untuk memvalidasi beberapa jawaban, dapatkah Anda mencoba zip zip yang dihasilkan dalam metode 3? Saya menduga ini akan mengurangi ukuran file menjadi sesuatu yang sebanding dengan metode 4.
Travis
7
Alih-alih $(ls -1), hanya menggunakan *: for x in *; zip all.zip *
muru
4
Jika Anda ingin melakukan kompresi padat dengan ZIP, berikut ini solusinya: pertama, buat ZIP yang tidak terkompresi yang berisi semua file Anda. Lalu, masukkan ZIP ke dalam ZIP terkompresi lain.
user20574

Jawaban:

129

Zip memperlakukan konten setiap file secara terpisah saat mengompresi. Setiap file akan memiliki aliran terkompresi sendiri. Ada dukungan dalam algoritma kompresi (biasanya DEFLATE ) untuk mengidentifikasi bagian berulang. Namun, tidak ada dukungan di Zip untuk menemukan redundansi antar file.

Itu sebabnya ada begitu banyak ruang ekstra ketika konten di beberapa file: itu menempatkan aliran terkompresi yang sama di file beberapa kali.

Alan Shutko
sumber
9
Itu juga mengapa beberapa alat kompresi memberi Anda pilihan untuk mengompresi file secara terpisah atau sebagai satu kesatuan. (Meskipun secara umum itu juga berarti Anda harus mendekompresi lebih banyak dari arsip daripada yang akan Anda lakukan jika Anda ingin melihat hanya satu file di dalamnya.)
JAB
28
@ JAB: Alat kompresi seperti 7z dan rar menggunakan istilah "solid" untuk mengemas beberapa file secara langsung ke aliran kompresi yang lebih besar. Dengan ukuran chunk yang moderat seperti 64MiB, akses acak ke satu file mungkin memerlukan dekompresi hingga 64MiB data dari awal blok kompresi tempat Anda berada. Anda bisa mendapatkan tradeoff yang layak antara akses acak dan menemukan redundansi cross-file. 7z dapat menggunakan skema kompresi LZMA yang lebih efektif (tetapi lebih lambat), yang merupakan keunggulan lain dibandingkan zip.
Peter Cordes
Apakah Anda mengatakan bahwa there is no support in Zip to find redundancy between filesada dalam spesifikasi file zip?
sixtyfootersdude
6
@sixtyfootersdude Banyak algoritma kompresi, seperti DEFLATE, beroperasi sebagai stream. Untuk memulihkan informasi yang cukup untuk mendekompres bagian dari aliran, Anda perlu memproses seluruh aliran hingga titik itu. Jika mereka mencoba menemukan redundensi antar file, Anda harus mendekompres semua 1000 file untuk sampai ke yang terakhir. Ini biasanya cara kerja tgz, sebenarnya. Namun, zip dirancang untuk memungkinkan Anda mengekstrak file individual. tgz dirancang untuk menjadi lebih lengkap atau tidak sama sekali
Cort Ammon
1
@sixtyfootersdude - itu benar. Mengutip Cort: Spesifikasi pkzip tidak mendukung cross-file yang berfungsi. Jika mereka melakukannya maka mengekstraksi satu file mungkin memerlukan seluruh arsip (dan setiap file) diekstraksi.
James Snell
48

Kompresi ZIP didasarkan pada pola berulang dalam data yang akan dikompresi, dan kompresi menjadi lebih baik semakin lama file, karena semakin banyak pola dapat ditemukan dan digunakan.

Sederhana, jika Anda mengompres satu file, kamus yang memetakan kode (pendek) ke pola (lebih lama) tentu terkandung dalam setiap file zip yang dihasilkan; jika Anda zip satu file panjang, kamus 'digunakan kembali' dan tumbuh lebih efektif di semua konten.

Jika file Anda bahkan sedikit mirip (seperti teks biasanya), penggunaan kembali 'kamus' menjadi sangat efisien, dan hasilnya adalah total zip yang jauh lebih kecil.

Aganju
sumber
3
ZIP melakukan pengarsipan dan kompresi. Apakah ini berarti bahwa ZIP mengkompres setiap file secara individual, bahkan jika semuanya berakhir dalam file ZIP yang sama?
gerrit
2
itu semacam harus - bayangkan Anda menghapus satu file, Anda tidak akan ingin menghabiskan setengah jam kembali mengompres sisanya dengan 'kamus' baru. - juga, mungkin diasumsikan bahwa file yang berbeda memerlukan 'kamus' yang sangat berbeda.
Aganju
2
Saya tidak mengerti mengapa harus begitu. Dengan alat Unix, saya pertama-tama akan mengarsipkan file dengan tar, kemudian kompres dengan gzip / bz2 / lzma. Algoritma kompresi tidak peduli berapa banyak file yang dikodekan dalam arsip. Juga, seberapa umumkah menghapus satu file dari arsip yang dikompresi? Saya tidak berpikir saya pernah melakukan itu.
gerrit
4
Saya tidak setuju, dan itu mungkin cara yang baik. Saya tidak merancang atau menulis ZIP. Saya baru saja mengatakan apa fungsinya ...
Aganju
16
@gerrit Ini memiliki masalah sendiri. Zip dirancang untuk memungkinkan Anda dengan cepat mengakses file apa pun dalam arsip - cobalah membongkar satu file dari arsip UHA 100 GiB dan Anda akan melihat mengapa mereka memilih cara ini. Ini juga dirancang untuk menambahkan - Anda dapat memiliki zip cadangan Anda dan terus menambahkan (atau mengganti) file yang diperlukan. Semua ini sangat membantu saat menggunakan arsip. Imbalannya adalah jika Anda mengompresi file yang sangat mirip (yang tidak terlalu umum), itu tidak dapat mengeksploitasi kesamaan untuk mengurangi ukuran arsip.
Luaan
43

Dalam Zip, setiap file dikompres secara terpisah. Yang sebaliknya adalah 'kompresi padat', yaitu file dikompresi bersama. 7-zip dan Rar menggunakan kompresi padat secara default. Gzip dan Bzip2 tidak dapat mengkompres banyak file sehingga Tar digunakan terlebih dahulu, memiliki efek yang sama seperti kompresi padat.

Karena file xml memiliki struktur yang sama dan mungkin konten yang serupa jika file dikompresi bersama, kompresi akan lebih tinggi.

Sebagai contoh jika file berisi string "<content><element name="dan kompresor telah menemukan string di file lain itu akan menggantinya dengan pointer kecil ke pertandingan sebelumnya, jika kompresor tidak menggunakan 'kompresi padat', arus pertama string di file akan direkam sebagai literal yang lebih besar.

ggf31416
sumber
9

Zip tidak hanya menyimpan konten file, Zip juga menyimpan metadata file seperti ID pengguna yang memiliki, izin, waktu pembuatan dan modifikasi, dan sebagainya. Jika Anda memiliki satu file, Anda memiliki satu set metadata; jika Anda memiliki 10.000 file, Anda memiliki 10.000 set metadata.

Mike Scott
sumber
3
Poin bagus, tetapi sistem meta data hanya memakan ruang 1,4MB. Lihat hasil edit saya.
sixtyfootersdude
1
Saya tidak terbiasa dengan algoritma zip, tetapi metadata tidak hanya informasi file, tetapi juga hal-hal seperti ukuran dan kamus, mungkin beberapa informasi tentang distribusi karakter. Kamus pada file teks yang tidak kosong akan menjadi nol. Mungkin itulah sebabnya Anda melihat metadata lebih besar di file xml Anda daripada file kosong Anda.
Ben Richards
Ini adalah pikiran pertamaku. Informasi Header Zip-File
WernerCD
Ini hanya menjelaskan perbedaan antara 2 dan 3 - bukan 4.
Luaan
@Luaan Tidak, dalam 2 dan 3 metadata untuk semua 10.000 file termasuk dalam file zip atau file, sehingga total ukuran file hampir sama ukurannya. Di 4, hanya ada metadata untuk satu file, dan file zip jauh lebih kecil.
Mike Scott
7

Opsi yang terlewatkan oleh OP adalah untuk meng-zip semua file bersamaan dengan kompresi dimatikan, kemudian zip zip yang dihasilkan dengan kompresi diatur ke maksimum. Ini secara kasar mengemulasi perilaku * nix .tar.Z, .tar.gz, .tar.bz, dll. Arsip terkompresi, dengan memungkinkan kompresi untuk mengeksploitasi redundansi melintasi batas file (yang tidak bisa dilakukan oleh algoritma ZIP saat dijalankan dalam satu lulus). Ini memungkinkan masing-masing file XML diekstraksi nanti, tetapi memaksimalkan kompresi. Kelemahannya adalah bahwa proses ekstraksi membutuhkan langkah ekstra, untuk sementara menggunakan lebih banyak ruang disk daripada yang diperlukan untuk .zip normal.

Dengan berbagai alat gratisan seperti 7-Zip untuk memperluas keluarga tar ke Windows, sebenarnya tidak ada alasan untuk tidak menggunakan .tar.gz atau .tar.bz, dll., Seperti Linux, OS X, dan BSD semuanya memiliki alat asli untuk memanipulasi mereka.

Monty Harder
sumber
gzip dan bzip2 mungkin berakhir lebih buruk karena mereka dirancang dengan mengompresi aliran dalam pikiran, sehingga mereka harus mulai mengeluarkan data terkompresi sebelum semua data untuk dikompresi bahkan diketahui.
rackandboneman
@ crackandboneman: Ini adalah tradeoff yang harus Anda buat saat mengompresi file lebih besar dari jumlah memori yang ingin Anda gunakan pada waktu kompresi. (Dan juga, jumlah waktu CPU yang diperlukan untuk menemukan sesuatu yang optimal secara global akan sangat besar.) Kamus kompresi yang sangat besar juga dapat meningkatkan memori yang diperlukan untuk dekompresi . Ini adalah opsi untuk LZMA ( xz/ 7-zip). Bagaimanapun, kamus adaptif dapat menangkap pola begitu mereka terlihat. Ini tidak seperti itu hanya membangun sistem pengkodean statis berdasarkan 32k pertama. Inilah sebabnya mengapa gzip tidak payah.
Peter Cordes
Saya sangat suka "trik" ini jika Anda harus tetap menggunakan format zip. Saya tidak setuju dengan "tanpa alasan untuk tidak menggunakan 7-zip" —jika saya mengirim file ke teman non-teknis, saya ingin memastikan mereka akan dapat membukanya dengan mudah. Jika saya mengirim ke klien bisnis, bahkan lebih dari itu.
Wowfunhappy
5

Format kompresi zip menyimpan dan mengkompres setiap file secara terpisah. Itu tidak mengambil keuntungan dari pengulangan di antara file, hanya dalam file.

Menggabungkan file memungkinkan zip untuk mengambil keuntungan dari pengulangan di semua file, menghasilkan kompresi yang lebih drastis.

Misalnya, katakanlah setiap file XML memiliki header tertentu. Header itu hanya terjadi sekali di setiap file tetapi diulang hampir identik di banyak file lainnya. Dalam metode 2 dan 3, zip tidak bisa dikompres untuk ini tetapi dalam metode 4 itu bisa.

BonsaiOak
sumber
3
Bagaimana ini berbeda dari salah satu dari 3 jawaban teratas yang sudah diposting 5 jam sebelumnya?
Xen2050
1
@ Xen2050 Tidak banyak perbedaan, saya hanya berpikir saya bisa menjelaskannya dengan lebih jelas.
BonsaiOak
1
@BonsaiOak - lalu tambahkan komentar ke jawaban yang benar atau edit jika Anda memiliki cukup perwakilan. Jika tidak, tetapi komentar Anda menambah kejelasan, orang lain mungkin mengambil ini dan mengedit posting.
AdamV
@ AdVV Saya mengerti maksud Anda. Jawaban saya saat ini tidak menambahkan informasi yang berguna, meskipun bisa dibilang ketika saya menulisnya. Sudah ada komentar yang sesuai di bawah jawaban pertama jadi saya tidak melihat gunanya menambahkannya juga. Apakah Anda mengatakan bahwa saya harus menutup jawaban saya? Apa salahnya membiarkannya tetap terbuka?
BonsaiOak
4

Di sebelah metadata Mike Scott disebutkan ada juga overhead dalam algoritma kompresi.

Ketika mengompresi sekelompok file kecil individual Anda harus sangat beruntung untuk dapat mengompres mereka bahwa itu hanya mengisi satu blok kompresi. Ketika mengompresi blok monolitik tunggal, sistem hanya dapat melanjutkan untuk mengalirkan data ke algoritmanya, mengabaikan 'batas' (karena kurangnya kata yang lebih baik) dari masing-masing file.

Juga ASCII diketahui memiliki faktor kompresi tinggi. plus xml sering sangat berulang-ulang menjadikan metadata sebagian besar dari data yang tidak dapat dengan mudah dikompresi sebagai konten xml.

Terakhir, jika memori berfungsi dengan benar, zip menggunakan sesuatu seperti pengkodean kamus, yang sangat efektif pada file ascii dan bahkan lebih pada XML karena pengulangannya

Dijelaskan Kompresi Data: http://mattmahoney.net/dc/dce.html

GapWim
sumber
3

Pertimbangkan XML ini:

<root>
  <element id="1" />
  <element id="2" /> 
  <other id="3" />
  ...
</root>

Suatu XML memiliki struktur yang sangat berulang, Zip mengambil keuntungan dari pengulangan tersebut untuk membangun kamus yang polanya lebih banyak terjadi dan kemudian, ketika mengompresi, menggunakan lebih sedikit bit untuk menyimpan pola yang lebih banyak diulang dan lebih banyak bit untuk menyimpan pola yang kurang berulang .

Ketika Anda menggabungkan file-file itu, file sumber (sumber untuk zip) besar tetapi berisi pola yang lebih berulang karena distribusi struktur membosankan XML diamortisasi di seluruh file besar, memberikan kesempatan kepada ZIP untuk menyimpan pola - pola tersebut. menggunakan bit lebih sedikit.

Sekarang, Jika Anda menggabungkan XML yang berbeda ke dalam satu file, bahkan ketika file-file tersebut memiliki nama tag yang sama sekali berbeda, algoritma kompresi akan menemukan distribusi pola terbaik di semua file dan bukan file per file.

Pada akhirnya, algoritma kompresi telah menemukan distribusi pola berulang terbaik.

rnrneverdies
sumber
-1

Selain jawaban 7-Zip, ada pendekatan lain yang tidak sebagus tetapi layak untuk diuji jika karena alasan tertentu Anda tidak ingin menggunakan 7-Zip:

Kompres file zip. Sekarang, biasanya file zip tidak dapat dimampatkan tetapi ketika itu berisi banyak file yang identik kompresor dapat menemukan redundansi ini dan kompres. Perhatikan bahwa saya juga melihat keuntungan kecil ketika berhadapan dengan sejumlah besar file tanpa redundansi. Jika Anda benar-benar peduli tentang ukuran, ada baiknya mencoba jika Anda memiliki banyak file di zip Anda.

Loren Pechtel
sumber
Itu hanya berfungsi jika Anda melakukan zip pertama dengan kompresi dimatikan seperti yang saya sebutkan di atas.
Monty Harder
@OnthHarder Saya sudah melihatnya bekerja dengan kompresi dihidupkan.
Loren Pechtel