farkmt2official 1
farkmt2official
kralhakan2009 1
kralhakan2009
Vahsi Uzman 1
Vahsi Uzman
Hikaye Ekle

[NODE JS] Zlib ile Dosya Sıkıştırma (gzip)

nodejs.png


[NODE JS] Zlib ile Dosya Sıkıştırma (gzip)​


Node.js dünyasında dosya sıkıştırma işlemleri, özellikle büyük veri kümeleriyle çalışırken hayat kurtaran bir beceridir. Ben ilk kez bu konuyla, bir projede günlük log dosyalarının sunucunun disk alanını tüketmeye başladığı zaman tanıştım. Her gün yüzlerce megabayt log üretiliyordu ve bunları ham halde saklamak hem maliyetli hem de gereksizdi. İşte tam bu noktada Node.js'in dahili zlib modülü devreye girdi.

Zlib modülü, Node.js çekirdeğinde yerleşik olarak gelen bir sıkıştırma kütüphanesidir. Herhangi bir harici paket yüklemenize gerek kalmadan doğrudan kullanabilirsiniz. Bu modül, gzip, deflate ve brotli gibi popüler sıkıştırma algoritmalarını destekler. Gzip özellikle web dünyasında yaygın olarak kullanılır çünkü neredeyse tüm tarayıcılar ve sunucular bu formatı destekler.

Sıkıştırma işleminin temel mantığı oldukça basittir. Bir dosyayı okursunuz, sıkıştırma algoritmasından geçirirsiniz ve çıktıyı yeni bir dosyaya yazarsınız. Ancak burada dikkat edilmesi gereken önemli bir nokta var: büyük dosyalarla çalışırken tüm dosyayı belleğe yüklemek yerine stream yapısını kullanmanız gerekir. Aksi takdirde bellek taşması yaşayabilirsiniz.

Gzip sıkıştırmasının çalışma prensibi, tekrar eden veri kalıplarını tespit edip bunları daha kısa temsillerle değiştirmektir. Metin tabanlı dosyalarda bu özellikle etkilidir çünkü metin dosyalarında tekrar eden kelimeler ve yapılar çok fazla bulunur. Örneğin bir JSON dosyasında sürekli tekrar eden anahtar isimleri, gzip tarafından çok verimli bir şekilde sıkıştırılır.

Pratikte gzip sıkıştırma seviyesini de ayarlayabilirsiniz. Seviye 1 en hızlı ama en az sıkıştırma oranını verirken, seviye 9 en yavaş ama en yüksek sıkıştırma oranını sağlar. Varsayılan seviye genellikle 6'dır ve çoğu senaryo için ideal bir denge sunar. Ben genellikle log dosyaları için seviye 9 kullanırım çünkü sıkıştırma süresi o kadar kritik değildir ama disk alanından tasarruf etmek önceliklidir.

Bir diğer önemli konu da hata yönetimidir. Sıkıştırma işlemi sırasında dosya erişim hataları, disk dolu hataları veya bozuk veri hataları oluşabilir. Bu yüzden her zaman hata dinleyicilerini eklemeniz ve uygun hata mesajları üretmeniz gerekir. Üretim ortamında bu tür hataları loglayarak sorunları hızlıca tespit edebilirsiniz.

Stream tabanlı sıkıştırma yaklaşımı, pipe mekanizmasıyla birleştirildiğinde hem bellek dostu hem de performanslı bir çözüm sunar. Kaynak dosyadan okunan veriler parça parça sıkıştırılır ve hedef dosyaya yazılır. Bu sayede gigabayt büyüklüğündeki dosyaları bile birkaç megabayt bellek kullanarak sıkıştırabilirsiniz. Bu yaklaşım, Node.js'in asenkron doğasıyla mükemmel uyum sağlar ve sunucunuzun diğer işlemleri de aksatmadan devam etmesini sağlar.

JavaScript:
const zlib = require('zlib');
const fs = require('fs');
const path = require('path');

// Basit gzip sıkıştırma fonksiyonu
function dosyaSikistir(kaynakYol, hedefYol) {
  return new Promise((resolve, reject) => {
    // Kaynak dosyanın varlığını kontrol et
    if (!fs.existsSync(kaynakYol)) {
      reject(new Error('Kaynak dosya bulunamadı: ' + kaynakYol));
      return;
    }

    const okumaStream = fs.createReadStream(kaynakYol);
    const yazmaStream = fs.createWriteStream(hedefYol);

    // Gzip sıkıştırma seçenekleri
    const gzipSecenekleri = {
      level: zlib.constants.Z_BEST_COMPRESSION, // Seviye 9 - en yüksek sıkıştırma
      memLevel: 8, // Bellek kullanım seviyesi
      strategy: zlib.constants.Z_DEFAULT_STRATEGY // Varsayılan strateji
    };

    const gzip = zlib.createGzip(gzipSecenekleri);

    // İlerleme takibi için değişkenler
    const dosyaBoyutu = fs.statSync(kaynakYol).size;
    let islenenBoyut = 0;

    okumaStream.on('data', (parca) => {
      islenenBoyut += parca.length;
      const yuzde = ((islenenBoyut / dosyaBoyutu) * 100).toFixed(1);
      process.stdout.write('
Sıkıştırma ilerlemesi: %' + yuzde);
    });

    // Hata dinleyicileri
    okumaStream.on('error', (hata) => {
      console.error('
Okuma hatası:', hata.message);
      reject(hata);
    });

    gzip.on('error', (hata) => {
      console.error('
Sıkıştırma hatası:', hata.message);
      reject(hata);
    });

    yazmaStream.on('error', (hata) => {
      console.error('
Yazma hatası:', hata.message);
      reject(hata);
    });

    yazmaStream.on('finish', () => {
      const orijinalBoyut = dosyaBoyutu;
      const sikistirilmisBoyut = fs.statSync(hedefYol).size;
      const oran = ((1 - sikistirilmisBoyut / orijinalBoyut) * 100).toFixed(1);

      console.log('
--- Sıkıştırma Tamamlandı ---');
      console.log('Orijinal boyut: ' + (orijinalBoyut / 1024).toFixed(2) + ' KB');
      console.log('Sıkıştırılmış boyut: ' + (sikistirilmisBoyut / 1024).toFixed(2) + ' KB');
      console.log('Sıkıştırma oranı: %' + oran);
      resolve({ orijinalBoyut, sikistirilmisBoyut, oran });
    });

    // Pipe ile sıkıştırma zinciri
    okumaStream.pipe(gzip).pipe(yazmaStream);
  });
}

// Birden fazla dosyayı toplu sıkıştırma
async function topluSikistir(dosyaListesi, hedefKlasor) {
  console.log('Toplu sıkıştırma başlatılıyor...');
  console.log('Toplam dosya sayısı: ' + dosyaListesi.length);

  // Hedef klasörü oluştur
  if (!fs.existsSync(hedefKlasor)) {
    fs.mkdirSync(hedefKlasor, { recursive: true });
    console.log('Hedef klasör oluşturuldu: ' + hedefKlasor);
  }

  const sonuclar = [];

  for (const dosya of dosyaListesi) {
    const dosyaAdi = path.basename(dosya);
    const hedefYol = path.join(hedefKlasor, dosyaAdi + '.gz');

    console.log('
İşleniyor: ' + dosyaAdi);

    try {
      const sonuc = await dosyaSikistir(dosya, hedefYol);
      sonuclar.push({ dosya: dosyaAdi, basarili: true, ...sonuc });
    } catch (hata) {
      sonuclar.push({ dosya: dosyaAdi, basarili: false, hata: hata.message });
      console.error('Dosya sıkıştırılamadı: ' + dosyaAdi);
    }
  }

  // Özet rapor
  console.log('
====== ÖZET RAPOR ======');
  const basariliSayi = sonuclar.filter(s => s.basarili).length;
  console.log('Başarılı: ' + basariliSayi + '/' + dosyaListesi.length);

  sonuclar.forEach(s => {
    if (s.basarili) {
      console.log('  ✓ ' + s.dosya + ' → %' + s.oran + ' küçültüldü');
    } else {
      console.log('  ✗ ' + s.dosya + ' → Hata: ' + s.hata);
    }
  });

  return sonuclar;
}

// Buffer üzerinden doğrudan sıkıştırma (küçük veriler için)
function veriSikistir(veri) {
  return new Promise((resolve, reject) => {
    const tampon = Buffer.isBuffer(veri) ? veri : Buffer.from(veri, 'utf-8');

    zlib.gzip(tampon, { level: 6 }, (hata, sonuc) => {
      if (hata) {
        reject(hata);
        return;
      }
      console.log('Orijinal veri boyutu: ' + tampon.length + ' byte');
      console.log('Sıkıştırılmış boyut: ' + sonuc.length + ' byte');
      resolve(sonuc);
    });
  });
}

// Kullanım örneği
async function main() {
  // Tek dosya sıkıştırma
  try {
    await dosyaSikistir('./buyuk-log.txt', './buyuk-log.txt.gz');
  } catch (hata) {
    console.error('İşlem başarısız:', hata.message);
  }

  // Metin verisini doğrudan sıkıştırma
  const metin = 'Bu bir test verisidir. '.repeat(1000);
  const sikistirilmis = await veriSikistir(metin);
  console.log('Sıkıştırılmış veri uzunluğu:', sikistirilmis.length, 'byte');
}

main().catch(console.error);

Zlib modülü, Node.js'in en güçlü dahili araçlarından biridir. Dosya sıkıştırma işlemlerini stream tabanlı yaklaşımla gerçekleştirdiğinizde hem bellek kullanımını optimize edersiniz hem de büyük dosyalarla sorunsuz çalışabilirsiniz. Özellikle log rotasyonu, yedekleme sistemleri ve veri arşivleme gibi senaryolarda bu bilgi vazgeçilmezdir.
 
Emeğiniz ve katkınız için teşekkür ederiz!
Konunuz gerekli incelemelerden geçerek onaylandı. Topluluğumuza katkılarınızın devamını bekliyoruz.
İyi forumlar! 🎉
 

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)

Geri
Üst