Merhabalar, bu
yazımda .Net Framework 2.0 ile beraber gelmiş olan GzipStream
sınıfına kısaca değineceğim. gzip gnu’nun sıkıştırma programıdır. UNIXte
.gz, VMSte -gz, MSDOSda, OS/2te .z uzantılı dosyalardır. (http://www.po.metu.edu.tr/links/inf/css25/bolum12.html#4.4)
GZip ifadesi "Gnu Zip" kelimesinin kısaltılmışıdır. Gzip in temelinde
ise deflate isimli sıkıştırma algoritması vardır.
Bu sınıf akım(diğer
adıyla stream)ları sıkıştırmak ve sıkıştırılmış akışları geri açmak için metotlar
ve özellikler sağlıyor. DeflateStream sınıfıyla beraber
System.IO.Compression isim alanında bulunuyor.
GzipStream sınıfı
System.IO isim alanında bulunan Stream sınıfından türetilmiştir, yani sınıfımızı
:
public
class GzipStream : Stream
şeklinde gösterebiliriz.
gzip veri formatımız DeflateStream sınıfıyla aynı algoritmayı kullanır fakat
diğer sıkıştırma metotlarını kullanabilmek için türetme yapabiliriz. Fakat gzip
algortimasını 4 GBden büyük dosyalar için kullanamayız.
DeflateStream ve
GzipStream sınıflarının sıkıştırma fonksiyonları stream açığa çıkarır. Veri
byte byte okunur. MSDNde belirtildiğine göre bu sınıflar sıkıştırılmamış dosyalar
için en iyidir fakat veri kaynağı önceden sıkıştırıldıysa boyut daha da artabilir.
Eğer GzipStream
sınıfından türetme yapmak isterseniz CanSeek ,CanWrite ve CanRead üyelerini
override etmelisiniz.
GzipStream sınıfının 2 tane yapıcı metodu vardır.
1-) GzipStream
(Stream , CompressionMode)
2-) GzipStream
(Stream , CompressionMode , boolean )
|
Birinici yapıcı
metotta belirtilen stream ve compressionmode
a göre GzipStream nesnesi yaratılır. Burada CompressionMode bir enum sabitidir.
Belirtilen streamin sıkıştırılacağını mı yoksa sıkıştırılmış streamin açılacağını
mı belirtir. 2 değer alır. Birisi CompressionMode.Compress
diğeri ise CompressionMode.Decompress’tir.
Msdn’den bu sınıfa
ait tüm metotları inceleyebilirsiniz. Bu yazımda sadece kısaca read ve write
metotlarından bahsedeceğim.
Read
Metodu: public override int Read(byte[] dizi,int ofset,int adet )
Bu metot adet kadar decompressed(sıkıştırıldıktan sonra geri açılmış) byte’ı
byte türden diziye atar.
Write Metodu: public
override void write ( byte[] dizi,int ofset,int sayac)
Bu metot ise dizideki
ofsetinci byte’dan başlayarak sayac kadar sıkıştırılmış byte’ı stream nesnesine
yazar.
Şimdi bir örnekle
fonksiyonların kullanım şeklini inceleyelim. Örneğimiz aşağıdaki gibi bir Windows
uygulamasından oluşmaktadır.
private
void button1_Click(object sender, EventArgs e)//Sıkıştır butonunun
{
string dosya="ilkdosya.doc";
if (File.Exists(dosya))
GZipTest.GZipCompress(dosya);
}
private void
button2_Click(object sender, EventArgs e)
{
string dosya = "yenidosya.gz";
if (File.Exists(dosya))
GZipTest.GZipDecompress(dosya);
}
|
Sıkıştır butonuna
tıklanınca ilkdosya.doc adındaki dosyayı sıkıştırır,sıkıştırılmış
dosyaya yenidosya.gz adını verdim. Geri aç butonuna tıklayınca ise yenidosya.gz
adındaki dosya geri açılır ve sondosya.doc isimli dosyaya geri açılmış içerik
yazılır. Bu işlemler aşağıdaki GzipTest adındaki sınıftaki GzipCompress ve GZipDecompress
metodları kullanılarak yapılıyor.
GZipTest Sınıfı :
public
class GZipTest
{
public static int ReadAllBytesFromStream(Stream
stream, byte[] buffer)
{
int offset
= 0;
int totalCount
= 0;
while (true)
{
int
bytesRead = stream.Read(buffer, offset, 100);
if
(bytesRead == 0)
{
break;
}
offset
+= bytesRead;
totalCount
+= bytesRead;
}
return totalCount;
}
public
static void GZipCompress(string dosya_adi)
{
FileStream
infile;
try
{
infile
= new FileStream(dosya_adi, FileMode.Open, FileAccess.Read, FileShare.Read);
byte[]
buffer = new byte[infile.Length];
int
count = infile.Read(buffer, 0, buffer.Length);
if
(count != buffer.Length)
{
infile.Close();
MessageBox.Show("Dosya
okuma sırasında sorun oluştu. ");
return;
}
infile.Close();
FileStream
fss = new FileStream("yenidosya.gz", FileMode.OpenOrCreate,
FileAccess.ReadWrite, FileShare.ReadWrite);
GZipStream
compressedzipStream = new GZipStream(fss, CompressionMode.Compress, true);
compressedzipStream.Write(buffer,
0, buffer.Length);
compressedzipStream.Close();
fss.Close();
}
catch (Exception
e)
{
MessageBox.Show("Error
occured. "+e.Message);
}
}
public
static void GZipDecompress(string filename)
{
FileStream
infile;
try
{
infile
= new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
byte[]
buffer = new byte[infile.Length];
int
count = infile.Read(buffer, 0, buffer.Length);
if
(count != buffer.Length)
{
infile.Close();
Console.WriteLine("Test
Failed: Unable to read data from file");
return;
}
infile.Close();
FileStream
fss = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite,
FileShare.ReadWrite);
GZipStream
zipStream = new GZipStream(fss, CompressionMode.Decompress);
byte[]
decompressedBuffer = new byte[40000];
zipStream.Read(decompressedBuffer,0,40000);
FileStream
sonst = new FileStream("sondosya.doc", FileMode.OpenOrCreate,
FileAccess.ReadWrite, FileShare.ReadWrite);
sonst.Write(decompressedBuffer,
0, 40000);
zipStream.Close();
}
catch (Exception
e)
{
MessageBox.Show("Error
occured. ");
}
}
}
|
GzipCompress altyordamında,
ilk önce parametre olarak geçirilen dosya okunuyor ve dosyanın içeriği buffer
adındaki byte türünden diziye atılıyor.
FileStream fss = new FileStream("yenidosya.gz", FileMode.OpenOrCreate,
FileAccess.ReadWrite, FileShare.ReadWrite);
GZipStream compressedzipStream = new GZipStream(fss,CompressionMode.Compress,
true);
compressedzipStream.Write(buffer, 0, buffer.Length);
Sonra yukarıdaki satırlarda compressedzipStream adında bir tane GZipStream nesnesi
oluşturuluyor ,CompressionMode’u Compress olarak belirtilerek sıkıştırma işlemi
yapılacağını belirtmiş oluyoruz ve ayrıca FileStream türündeki fss’yi ilk argüman
olarak geçirdiğimize dikkat edin.
compressedzipStream.Write(buffer, 0, buffer.Length);
satırında ise bufferdaki bilgiler sıkıştırılarak streame yazılıyor yani
sıkıştırılmış verileri fss adındaki stream nesnesi ile yenidosya.gz’ye yazmış
olduk.
zipStream.Read(decompressedBuffer,0,40000);
FileStream sonst = new FileStream("sondosya.doc", FileMode.OpenOrCreate,
FileAccess.ReadWrite, FileShare.ReadWrite);
sonst.Write(decompressedBuffer, 0, 40000);
Decompress metodunda ise bu sefer sıkıştırılmış olan streamden okuyacağımız
için read metodunu kullanıyoruz ve sıkıştırılmış dosyanın içeriğini decompressedBuffer
içine atıyoruz. Ordaki 40000 gibi rakamlar sizi şaşıtmasın. Sıkıştırılmış dosyanın
açıldığında kaç byte olacağını bilemediğim için FileStream sınıfına ait yazma
fonksiyonunda 3. parametre olarak, ilkdosya.doc adındaki dosyamın boyutuna yakın
bir değer olarak ,40000 değerini verdim.
Kaynak
: MSDN
Makale:
GZip ile Sıkıştırma İşlemi C#, Visual C# ve .NET Ömer Özsakarya
|