Gzip dosyaları için bir sıkıştırma aracı yazma


11

Bu zorluğun görevi aşağıdaki gibidir:

Stdin'den veya başka herhangi bir yerden makul boyutta bir dosyayı (diyelim <16 MB) okuyan bir program yazın (ancak istediğiniz, ancak kodlanmaması gerekir) ve sıkıştırılmış çıktıyı stdout'a koyun. Çıktı geçerli bir gzip sıkıştırılmış dosya olmalıdır ve sıkıştırılmış dosya gunzip üzerinden çalışıyorsa, önceki dosyayla tam olarak aynı dosyayı vermelidir.

kurallar

  • Kullanılan programlama dili bu yarışma başlamadan önce bilinmelidir
  • Programınızın puanı, kaynak kodun veya birleştirilmiş programın karakter sayısıdır (daha kısa ne olursa olsun)
  • Mevcut herhangi bir sıkıştırma kütüphanesini kullanmanıza izin verilmez.
  • İyi eğlenceler!

2
Yerleşik kitaplıkların kullanımına izin veriliyor mu?
hallvabo

@hallvabo: Hayır. Bunu unuttum. Thx
FUZxxl

2
Muhtemelen bunu yapmanın en iyi yolu, girdiyi her bloğun başlangıcında "aşağıdaki blok sıkıştırılmamış" işaretleriyle doldurmaktır.
Anon.

gzip bir programlama dilidir. Gerçi tam bir Turing değil.
Alexandru

1
Bu, Silahlar ve Fermuarlar problemiyle hemen hemen aynı . Kodgolf.com tarafından desteklenmeyen bir dilde (örneğin, GolfScript) desteklemeyen bir dilde çözmek istemiyorsa, neden herkes kodlarını burada codegolf.com yerine yayınlayacaktır?
Chris Jester-Young

Yanıtlar:


10

C # (534 karakter)

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);}}}

Çok daha okunabilir:

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);
        }
    }
}

Yorumlar:

  • İlk komut satırı argümanı olarak dosya yolunu bekler.

  • Çıktı dosyası + girdi dosyasıdır .gz.

  • Gzip, deflate veya CRC32 yapmak için herhangi bir kütüphane kullanmıyorum. Hepsi orada.

  • Bu “kompresör” dosya boyutunu 6 kat arttırır. Ama geçerli gzip formatında!

  • GNU gunzip ve WinRAR kullanılarak test edildi.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.