Supongamos que tengo 10,000 archivos XML. Ahora supongamos que quiero enviárselos a un amigo. Antes de enviarlos, me gustaría comprimirlos.
Método 1: no comprimirlos
Resultados:
Resulting Size: 62 MB
Percent of initial size: 100%
Método 2: comprime cada archivo y envíale 10,000 archivos xml
Mando:
for x in $(ls -1) ; do echo $x ; zip "$x.zip" $x ; done
Resultados:
Resulting Size: 13 MB
Percent of initial size: 20%
Método 3: crear un único zip que contenga 10,000 archivos xml
Mando:
zip all.zip $(ls -1)
Resultados:
Resulting Size: 12 MB
Percent of initial size: 19%
Método 4: Concatenar los archivos en un solo archivo y comprimirlo
Mando:
cat *.xml > oneFile.txt ; zip oneFile.zip oneFile.txt
Resultados:
Resulting Size: 2 MB
Percent of initial size: 3%
Preguntas:
- ¿Por qué obtengo resultados tan dramáticamente mejores cuando solo estoy comprimiendo un solo archivo?
- Esperaba obtener resultados drásticamente mejores con el método 3 que con el método 2, pero no lo hago. ¿Por qué?
- ¿Es específico este comportamiento
zip
? Si lo intentaragzip
, ¿obtendría resultados diferentes?
Información adicional:
$ 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)
Editar: metadatos
Una respuesta sugiere que la diferencia son los metadatos del sistema que se almacenan en el archivo zip. No creo que este pueda ser el caso. Para probar, hice lo siguiente:
for x in $(seq 10000) ; do touch $x ; done
zip allZip $(ls -1)
El zip resultante es 1.4MB. Esto significa que todavía hay ~ 10 MB de espacio inexplicable.
.tar.gz
en lugar de simplemente comprimir todo el directorio.$(ls -1)
, simplemente use*
:for x in *
;zip all.zip *
Respuestas:
Zip trata el contenido de cada archivo por separado cuando se comprime. Cada archivo tendrá su propia secuencia comprimida. Hay soporte dentro del algoritmo de compresión (típicamente DEFLATE ) para identificar secciones repetidas. Sin embargo, no hay soporte en Zip para encontrar redundancia entre archivos.
Es por eso que hay tanto espacio extra cuando el contenido está en múltiples archivos: está poniendo la misma secuencia comprimida en el archivo varias veces.
fuente
there is no support in Zip to find redundancy between files
está en la especificación del archivo zip?La compresión ZIP se basa en patrones repetitivos en los datos a comprimir, y la compresión mejora a medida que el archivo es más largo, ya que se pueden encontrar y usar más patrones más largos.
Simplificado, si comprime un archivo, el diccionario que asigna códigos (cortos) a patrones (más largos) está necesariamente contenido en cada archivo zip resultante; Si comprime un archivo largo, el diccionario se 'reutiliza' y se vuelve aún más efectivo en todo el contenido.
Si sus archivos son incluso un poco similares (como siempre lo es el texto), la reutilización del 'diccionario' se vuelve muy eficiente, y el resultado es un zip total mucho más pequeño.
fuente
En Zip, cada archivo se comprime por separado. Lo contrario es 'compresión sólida', es decir, los archivos se comprimen juntos. 7-zip y Rar usan compresión sólida por defecto. Gzip y Bzip2 no pueden comprimir varios archivos, por lo que Tar se usa primero, teniendo el mismo efecto que la compresión sólida.
Como el archivo xml tiene una estructura similar y probablemente un contenido similar, si los archivos se comprimen juntos, la compresión será mayor.
Por ejemplo, si un archivo contiene la cadena
"<content><element name="
y el compresor ya encontró esa cadena en otro archivo, lo reemplazará con un pequeño puntero a la coincidencia anterior, si el compresor no usa 'compresión sólida' la primera vez que la cadena aparece en el el archivo se grabará como un literal que es más grande.fuente
Zip no solo almacena el contenido del archivo, sino que también almacena los metadatos del archivo, como la identificación del usuario propietario, los permisos, los tiempos de creación y modificación, etc. Si tiene un archivo, tiene un conjunto de metadatos; si tiene 10,000 archivos, tiene 10,000 conjuntos de metadatos.
fuente
Una opción perdida por el OP es comprimir todos los archivos junto con la compresión desactivada, luego comprimir el zip resultante con la compresión establecida al máximo. Esto emula aproximadamente el comportamiento de los archivos comprimidos * nix .tar.Z, .tar.gz, .tar.bz, etc., al permitir que la compresión explote las redundancias a través de los límites de los archivos (que el algoritmo ZIP no puede hacer cuando se ejecuta en un solo archivo) pasar). Esto permite que los archivos XML individuales se extraigan más tarde, pero maximiza la compresión. La desventaja es que el proceso de extracción requiere un paso adicional, utilizando temporalmente mucho más espacio en disco del que se necesitaría para un .zip normal.
Con la ubicuidad de herramientas gratuitas como 7-Zip para extender la familia tar a Windows, realmente no hay razón para no usar un .tar.gz o .tar.bz, etc., ya que Linux, OS X y los BSD tienen todos herramientas nativas para manipularlos.
fuente
xz
/ 7-zip). De todos modos, los diccionarios adaptativos pueden detectar patrones una vez que son visibles. No es que solo construya un sistema de codificación estático basado en los primeros 32k. Es por eso que gzip no apesta.El formato de compresión zip almacena y comprime cada archivo por separado. No aprovecha la repetición entre archivos, solo dentro de un archivo.
La concatenación del archivo permite que zip aproveche las repeticiones en todos los archivos, lo que resulta en una compresión drásticamente mayor.
Por ejemplo, supongamos que cada archivo XML tiene un encabezado determinado. Ese encabezado solo aparece una vez en cada archivo, pero se repite casi de manera idéntica en muchos otros archivos. En los métodos 2 y 3, zip no pudo comprimir esto, pero en el método 4 sí pudo.
fuente
Junto a los metadatos que mencionó Mike Scott, también hay una sobrecarga en el algoritmo de compresión.
Al comprimir un montón de archivos pequeños individuales, tendrá que ser muy afortunado para poder comprimirlos, ya que simplemente llena un bloque de compresión. Al comprimir un solo bloque monolítico, el sistema puede continuar transmitiendo datos a su algoritmo, ignorando los 'límites' (por falta de una mejor palabra) de los archivos individuales.
También se sabe que ASCII tiene un alto factor de compresión. Además, xml suele ser muy repetitivo, lo que convierte a los metadatos en una gran parte de los datos que no se pueden comprimir tan fácilmente como el contenido xml.
Por último, si la memoria funciona correctamente, zip usa algo como la codificación de diccionario, que es especialmente eficaz en archivos ASCII y aún más en XML debido a su repetitividad
Compresión de datos explicada: http://mattmahoney.net/dc/dce.html
fuente
Considere este XML:
Un XML tiene una estructura muy repetitiva, Zip aprovecha esas repeticiones para construir un diccionario cuyo patrón tiene más ocurrencias y luego, al comprimir, usa menos bits para almacenar más patrones repetidos y más bits para almacenar patrones menos repetidos .
Cuando concatena esos archivos, el archivo fuente (la fuente para zip) es grande pero contiene patrones mucho más repetidos porque la distribución de las estructuras aburridas de un XML se amortiza en el archivo completo grande, dando la posibilidad de que ZIP almacene esos patrones. usando menos pedazos.
Ahora, si combina diferentes XML en un solo archivo, incluso cuando esos archivos tienen nombres de etiquetas completamente diferentes, el algoritmo de compresión encontrará la mejor distribución de patrones en todos los archivos y no archivo por archivo.
Finalmente, el algoritmo de compresión ha encontrado la mejor distribución de patrones repetidos.
fuente
Además de la respuesta 7-Zip, hay otro enfoque que no es tan bueno pero que valdría la pena probar si por alguna razón no desea usar 7-Zip:
Comprime el archivo zip. Ahora, normalmente un archivo zip es incompresible, pero cuando contiene muchos archivos idénticos, el compresor puede encontrar esta redundancia y comprimirla. Tenga en cuenta que también he visto una pequeña ganancia al tratar con grandes cantidades de archivos sin redundancia. Si realmente te importa el tamaño, vale la pena intentarlo si tienes una gran cantidad de archivos en tu zip.
fuente