Por que o Zip é capaz de compactar um único arquivo menor que vários arquivos com o mesmo conteúdo?

121

Suponha que eu tenha 10.000 arquivos XML. Agora suponha que eu queira enviá-los para um amigo. Antes de enviá-los, gostaria de compactá-los.

Método 1: não compactá-los

Resultados:

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

Método 2: Compacte todos os arquivos e envie-lhe 10.000 arquivos xml

Comando:

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: criar um único zip contendo 10.000 arquivos xml

Comando:

zip all.zip $(ls -1)

Resultados:

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

Método 4: Concatene os arquivos em um único arquivo & zip-lo

Comando:

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

Resultados:

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

Perguntas:

  • Por que obtenho resultados tão melhores quando estou apenas compactando um único arquivo?
  • Eu esperava obter resultados drasticamente melhores usando o método 3 do que o método 2, mas não o faço. Por quê?
  • Esse comportamento é específico para zip ? Se eu tentasse usar gzip , obteria resultados diferentes?

Informações adicionais:

$ 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: dados meta

Uma resposta sugere que a diferença são os metadados do sistema que estão armazenados no zip. Eu não acho que isso possa ser o caso. Para testar, fiz o seguinte:

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

O zip resultante é de 1,4 MB. Isso significa que ainda há ~ 10 MB de espaço inexplicado.

    
por sixtyfootersdude 14.12.2015 / 18:30

9 respostas

126

O Zip trata o conteúdo de cada arquivo separadamente ao compactar. Cada arquivo terá seu próprio fluxo compactado. Há suporte dentro do algoritmo de compressão (normalmente DEFLATE ) para identificar seções repetidas. No entanto, não há suporte no Zip para encontrar redundância entre os arquivos.

É por isso que há muito espaço extra quando o conteúdo está em vários arquivos: está colocando o mesmo fluxo compactado no arquivo várias vezes.

    
por 14.12.2015 / 20:24
47

A compactação ZIP é baseada em padrões repetitivos nos dados a serem compactados, e a compactação fica melhor quanto mais tempo o arquivo estiver, já que mais e mais padrões podem ser encontrados e usados.

Simplificado, se você compactar um arquivo, o dicionário que mapeia códigos (curtos) para padrões (mais longos) é necessariamente contido em cada arquivo zip resultante; Se você compactar um arquivo longo, o dicionário será "reutilizado" e ficará ainda mais eficaz em todo o conteúdo.

Se seus arquivos são um pouco parecidos (como o texto sempre é), a reutilização do 'dicionário' se torna muito eficiente, e o resultado é um zip total muito menor.

    
por 14.12.2015 / 19:48
42

No Zip, cada arquivo é compactado separadamente. O oposto é "compactação sólida", ou seja, os arquivos são compactados juntos. 7-zip e Rar usam compactação sólida por padrão. O Gzip e o Bzip2 não podem compactar vários arquivos, de forma que o Tar seja usado primeiro, com o mesmo efeito da compactação sólida.

Como o arquivo xml tem estrutura semelhante e, provavelmente, conteúdo semelhante, se os arquivos forem compactados juntos, a compactação será maior.

Por exemplo, se um arquivo contiver a string "<content><element name=" e o compressor já encontrar essa string em outro arquivo, ele será substituído por um pequeno ponteiro para a correspondência anterior, se o compressor não usar 'compactação sólida', o primeiro A ocorrência da string no arquivo será registrada como um literal que é maior.

    
por 14.12.2015 / 21:02
9

O Zip não armazena apenas o conteúdo do arquivo, ele também armazena metadados de arquivos como o ID do usuário, as permissões, os horários de criação e modificação e assim por diante. Se você tiver um arquivo, você tem um conjunto de metadados; Se você tiver 10 mil arquivos, terá 10 mil conjuntos de metadados.

    
por 14.12.2015 / 18:38
6

Uma opção perdida pelo OP é zipar todos os arquivos junto com a compactação desativada e, em seguida, zipar o zip resultante com a compactação configurada para o máximo. Isso praticamente emula o comportamento dos arquivos compactados * nix .tar.Z, .tar.gz, .tar.bz, etc., permitindo que a compactação explore as redundâncias nos limites dos arquivos (que o algoritmo ZIP não pode executar quando executado em um único arquivo). passar). Isso permite que os arquivos XML individuais sejam extraídos posteriormente, mas maximiza a compactação. A desvantagem é que o processo de extração requer a etapa extra, usando temporariamente muito mais espaço em disco do que seria necessário para um .zip normal.

Com a onipresença de ferramentas gratuitas como o 7-Zip para estender a família de tar ao Windows, não há realmente nenhuma razão para não usar um .tar.gz ou .tar.bz, etc., como o Linux, OS X e o Todos os BSDs possuem ferramentas nativas para manipulá-los.

    
por 15.12.2015 / 16:50
5

O formato de compactação zip armazena e compacta cada arquivo separadamente. Não tira proveito da repetição entre arquivos, somente dentro de um arquivo.

Concatenar o arquivo permite que o zip aproveite as repetições em todos os arquivos, resultando em uma drástica maior compactação.

Por exemplo, digamos que cada arquivo XML tenha um determinado cabeçalho. Esse cabeçalho só ocorre uma vez em cada arquivo, mas é repetido quase de forma idêntica em muitos outros arquivos. Nos métodos 2 e 3, o zip não podia ser compactado para isso, mas no método 4, podia.

    
por 15.12.2015 / 02:19
4

Ao lado dos metadados que Mike Scott mencionou, há também sobrecarga no algoritmo de compactação.

Ao compactar vários pequenos arquivos individuais, você terá muita sorte em compactá-los para preencher um bloco de compactação. Ao compactar um único bloco monolítico, o sistema pode continuar a transmitir dados para seu algoritmo, ignorando os "limites" (por falta de uma palavra melhor) dos arquivos individuais.

O ASCII também é conhecido por ter um alto fator de compactação. Além disso, o xml costuma ser muito repetitivo, tornando os metadados uma grande parte dos dados que não podem ser facilmente compactados como o conteúdo xml.

Por fim, se a memória funcionar corretamente, o zip usa algo como a codificação do dicionário, o que é especialmente eficaz em arquivos ascii e mais ainda em XML devido à repetitividade deles

Compressão de dados explicada: link

    
por 14.12.2015 / 19:02
3

Considere este XML:

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

Um XML tem uma estrutura muito repetitiva, o Zip aproveita essas repetições para construir um dicionário do qual padrão tem mais ocorrências e então, ao compactar, usa menos bits para armazenar mais repetidas padrões e mais bits para armazenar padrão menos repetido.

Quando você concatena esses arquivos, o arquivo de origem (a origem do zip) é grande, mas contém muito mais padrões repetidos porque a distribuição das estruturas chatas de um XML são amortizadas no arquivo inteiro grande, dando a chance de ZIP para armazenar os padrão usando menos bits.

Agora, se você combinar XML diferente em um único arquivo, mesmo quando esses arquivos tiverem nomes de tags completamente diferentes, o algoritmo de compactação encontrará a melhor distribuição padrão em todos os arquivos e não arquivo por arquivo.

Em última análise, o algoritmo de compressão encontrou a melhor distribuição de padrões repetidos.

    
por 16.12.2015 / 02:27
-1

Além da resposta do 7-Zip, há outra abordagem que não é tão boa, mas valeria a pena ser testada se, por algum motivo, você não quiser usar o 7-Zip:

Compacte o arquivo zip. Agora, normalmente um arquivo zip é incompressível, mas quando ele contém muitos arquivos idênticos, o compressor pode encontrar essa redundância e compactá-lo. Note que eu também vi um pequeno ganho ao lidar com um grande número de arquivos sem redundância. Se você realmente se importa com tamanho, vale a pena tentar se você tiver muitos arquivos no seu zip.

    
por 17.12.2015 / 02:09

Tags