Écrire un utilitaire de compression pour les fichiers gzip

11

La tâche de ce défi est la suivante:

Écrivez un programme qui lit un fichier de taille raisonnable (disons <16 Mo) depuis stdin ou n'importe où ailleurs (comme vous voulez, mais ne doit pas être codé en dur), et placez la sortie compressée sur stdout. La sortie doit être un fichier compressé gzip valide et si le fichier compressé passe par gunzip, il devrait produire exactement le même fichier qu'auparavant.

Règles

  • Le langage de programmation utilisé doit être connu avant le début de ce concours
  • Le score de votre programme est le nombre de caractères du code source ou du programme assemblé (ce qui est plus court)
  • Vous n'êtes pas autorisé à utiliser tout type de bibliothèques de compression existantes.
  • S'amuser!
FUZxxl
la source
2
L'utilisation des bibliothèques intégrées est-elle autorisée?
hallvabo
@hallvabo: Non. J'ai oublié ça. Thx
FUZxxl
2
La meilleure façon de procéder est probablement de remplir l'entrée avec les marqueurs "le bloc suivant n'est pas compressé" au début de chaque bloc.
Anon.
gzip est un langage de programmation. Pas un Turing complet cependant.
Alexandru
1
Ceci est à peu près identique au problème des armes à feu et des zips . Pourquoi quelqu'un publierait ses réponses ici plutôt que sur codegolf.com me dépasse, à moins qu'il ne veuille le résoudre dans un langage non pris en charge par codegolf.com (par exemple, GolfScript).
Chris Jester-Young

Réponses:

10

C # (534 caractères)

using System.IO;using B=System.Byte;class X{static void Main(string[]a){var f=File.ReadAllBytes(a[0]);int l=f.Length,i=0,j;var p=new uint[256];for(uint k=0,r=0;k<256;r=++k){for(j=0;j<8;j++)r=r>>1^(r&1)*0xedb88320;p[k]=r;}uint c=~(uint)0,n=c;using(var o=File.Open(a[0]+".gz",FileMode.Create)){o.Write(new B[]{31,139,8,0,0,0,0,0,4,11},0,10);for(;i<l;i++){o.Write(new B[]{(B)(i<l-1?0:1),1,0,254,255,f[i]},0,6);c=p[(c^f[i])&0xFF]^c>>8;}c^=n;o.Write(new[]{(B)c,(B)(c>>8),(B)(c>>16),(B)(c>>24),(B)l,(B)(l>>8),(B)(l>>16),(B)(l>>24)},0,8);}}}

Beaucoup plus lisible:

using System.IO;
using B = System.Byte;
class X
{
    static void Main(string[] a)
    {
        // Read file contents
        var f = File.ReadAllBytes(a[0]);
        int l = f.Length, i = 0, j;

        // Initialise table for CRC hashsum
        var p = new uint[256];
        for (uint k = 0, r = 0; k < 256; r = ++k)
        {
            for (j = 0; j < 8; j++)
                r = r >> 1 ^ (r & 1) * 0xedb88320;
            p[k] = r;
        }

        uint c = ~(uint) 0, n = c;

        // Write the output file
        using (var o = File.Open(a[0] + ".gz", FileMode.Create))
        {
            // gzip header
            o.Write(new B[] { 31, 139, 8, 0, 0, 0, 0, 0, 4, 11 }, 0, 10);
            for (; i < l; i++)
            {
                // deflate block header plus one byte of payload
                o.Write(new B[] { (B) (i < l - 1 ? 0 : 1), 1, 0, 254, 255, f[i] }, 0, 6);
                // Compute CRC checksum
                c = p[(c ^ f[i]) & 0xFF] ^ c >> 8;
            }
            c ^= n;
            o.Write(new[] {
                // CRC checksum
                (B) c, (B) (c >> 8), (B) (c >> 16), (B) (c >> 24),
                // original file size
                (B) l, (B) (l >> 8), (B) (l >> 16), (B) (l >> 24)
            }, 0, 8);
        }
    }
}

Commentaires:

  • Attend le chemin d'accès au fichier comme premier argument de ligne de commande.

  • Le fichier de sortie est le fichier d'entrée + .gz.

  • Je n'utilise aucune bibliothèque pour faire le gzip, le dégonflage ou le CRC32. Tout est là-dedans.

  • Ce «compresseur» augmente la taille du fichier d'un facteur 6. Mais il est au format gzip valide!

  • Testé avec GNU gunzip et WinRAR.

Timwi
la source