فشرده کردن و از حالت فشرده در آوردن یک فایل متنی

بهترین ایده برای فایلهایی که حجم آنها زیاد شده است، این است که آنها را فشرده کنیم. فشرده سازی پروسه کاهش حجم یک فایل است. این فرایند شامل یافتن ورودی‌های زائد و تکرار شده در یک فایل و تبدیل آنها به یک ورودی ساده است (یعنی اگر در یک فایل مثلاً 100 بار کلمه Hello به کار رفته باشد آنها را به یک کلمه Hello در نظر می‌گیرد). کاهش حجم فایل‌ها در وب بیشتر کاربرد دارد. می‌توان با کاهش حجم صفحات وب سرعت بارگذاری یک وب سایت را بالا برد. از این فرایند همچنین می‌توان برای گرفتن پشتیبان یا بایگانی فایلها و نیز به اشتراک گذاشتن یک فایل در اینترنت (حجم فایل را کم کرده تا سریعتر آپلود و دانلود شود) استفاده نمود. از نرم افزارهای مختلفی مانند WinRar و WinZip می‌توان برای فشرده سازی استفاده نمود. اگر با فایلهایی که دارای پسوند zip. و rar. هستند مواجه شدید بدانید که این فایلها فشرده شده‌اند و حجم آنها در مقایسه با حالت عادی‌شان (غیر فشرده‌شان) کمتر است.

فشرده سازی فایلها با استفاده از کلاس‌های GzipStream و DeflateStream

کتابخانه کلاس دات نت، دارای کلاس‌ها و متدهایی جهت فشرده سازی و باز کردن فایل‌ها از حالت فشرده می‌باشد. این کلاس‌ها از الگوریتم GZIP یا Deflate جهت فشرده سازی فایلها استفاده می‌کنند. در این درس می‌خواهیم یک فایل متنی را به راحتی فشرده کنیم. شما می‌توانید برای فشرده کردن فایلها و باز کردن فایها از حالت فشرده از کلاس GzipStream یا DeflateStream استفاده کنید. کارکرد این دو کلاس تقریباً شبیه هم است. این کلاس‌ها به یک شیء از FileStream که به یک فایل اشاره می‌کند، نیاز دارند. اجازه بدهید که نحوه استفاده به موقع از این کلاس‌ها را توضیح دهیم. در زیر دو مجموعه کد مربوط به دو کلاس ذکر شده است. یک برنامه کنسول با نام TextFileCompression ایجاد کنید. دو فضای نام لازم برای برنامه‌مان را وارد نمایید.

using System.IO;
using System.IO.Compression;

ابتدا حجم یک فایل را در حالت فشرده و غیر فشرده مقایسه می‌کنیم. کد زیر را برای ایجاد یک فایل متنی بدون هیچ فشردگی می‌نویسیم:

   1: static void Main(string[] args)
   2: {
   3:     StringBuilder data = new StringBuilder();
   4: 
   5:     for (int i = 0; i < 1000; i++)
   6:     {
   7:         data.AppendLine("The quick brown fox jumps over the lazy dog.");
   8:     }
   9: 
  10:     Console.WriteLine("A compressed file was created!");
  11: 
  12:     try
  13:     {
  14:         FileStream stream = new FileStream(@"C:compressedFile.txt",
  15:             FileMode.Create, FileAccess.Write);
  16: 
  17:         StreamWriter writer = new StreamWriter(stream);
  18: 
  19:         writer.Write(data.ToString());
  20:         writer.Close();
  21:     }
  22:     catch (IOException ex)
  23:     {
  24:         Console.WriteLine(ex.Message);
  25:     }
  26: }

خطوط 8-3، 1000 خط ساختگی را در داخل فایل متنی می‌نویسد. خطوط 12 تا 25 یک فایل متنی را همانطور که در درس‌های قبلی یاد گرفتیم ایجاد می‌کنند. توجه کنید که ما تا الان هیچ عملی جهت فشرده کردن فایل انجام نداده‌ایم. همانطور که در خط 14 مشاهده می‌کنید یک فایل متنی در C:compressedFile.txt ایجاد می‌شود. اگر به مسیر بالا رفته و حجم فایل مورد نظر را چک کنید مشاهده می‌کنید که حجم آن در حدود 45 کیلو بایت است. حال اجازه بدهید که از کلاس‌های فضای نام System.IO.Compression جهت فشرده سازی استفاده کنیم. در مثال زیر از GzipStream و در مثال بعد از DeflateStream جهت فشرده سازی فایل مذکور استفاده می‌کنیم :

   1: static void Main(string[] args)
   2: {
   3:     StringBuilder data = new StringBuilder();
   4: 
   5:     for (int i = 0; i < 1000; i++)
   6:     {
   7:         data.AppendLine("The quick brown fox jumps over the lazy dog.");
   8:     }
   9: 
  10:     Console.WriteLine("A compressed file was created!");
  11: 
  12:     try
  13:     {
  14:         FileStream stream = new FileStream(@"C:compressedFile.txt",
  15:             FileMode.Create, FileAccess.Write);
  16: 
  17:         GZipStream gzip = new GZipStream(stream, CompressionMode.Compress);
  18: 
  19:         StreamWriter writer = new StreamWriter(gzip);
  20: 
  21:         writer.Write(data.ToString());
  22:         writer.Close();
  23:     }
  24:     catch (IOException ex)
  25:     {
  26:         Console.WriteLine(ex.Message);
  27:     }
  28: }

این مثال تقریباً شبیه به مثال صفحه قبل است و تفاوت آنها در خطوط 17 و 19 می‌باشد. در خط 17 شیء GzipStream از الگوریتم GZIP جهت فشرده سازی استفاده می‌کند. در داخل سازنده (خط 17)، شیء ایجاد شده از FileStream یعنی straem را قرار می‌دهیم. دومین پارامتر سازنده یک مقدار از نوع شمارشی CompressionMode است که شامل دو مقدار Compress و Decompress می‌باشد. برای ایجاد فایل‌های فشرده از مقدار CompressionMode.Compress استفاده می‌کنیم. در خط 19 به جای ارسال FileStream به StreamWriter، شیء ایجاد شده GzipStream را ارسال می‌کنیم. وقتی که متد Write() در خط 21 را فراخوانی می‌کنیم، داده‌های نوشته شده به طور خودکار با استفاده از الگوریتم GZIP فشرده می‌شوند. به یاد دارید که حجم فایل در حالت غیر فشرده در حدود 45kb بود. حال اجازه بدهید که نگاهی به سایز جدید فایل در حالت فشرده بیندازیم. مشاهده می‌کنید که حجم آن در این حالت 660 بایت یا در حدود 1kb می‌باشد، که 44KB کمتر از فایل غیر فشرده‌ای است، که قبلاً ایجاد کردیم. مقدار کاهش یک فایل به مقدار زوائد و کل سایز فایل بستگی دارد. از آنجاییکه فایل اصلی شامل یک جمله است که 1000 بار تکرار شده است کار فشرده سازی فایل راحت‌تر می‌شود.
اگر فایل متنی فشرده شده را باز کنید نمی‌توانید آن را بخوانید چون محتویات آن تغییر کرده است. همانطور که در مثال زیر مشاهده خواهید کرد کلاس DeflateStream بسیار شبیه به کلاس GzipStream می‌باشد. سایز فایل فشرده ایجاد شده توسط الگوریتم بالا در حدود 640bytes است که کمی کمتر از حالت فشرده آن به وسیله الگوریتم Gzip می‌باشد.

   1: static void Main(string[] args)
   2: {
   3:     StringBuilder data = new StringBuilder();
   4: 
   5:     for (int i = 0; i < 1000; i++)
   6:     {
   7:         data.AppendLine("The quick brown fox jumps over the lazy dog.");
   8:     }
   9: 
  10:     Console.WriteLine("A compressed file was created!");
  11: 
  12:     try
  13:     {
  14:         FileStream stream = new FileStream(@"C:compressedFile.txt",
  15:             FileMode.Create, FileAccess.Write);
  16: 
  17:         DeflateStream deflate = new DeflateStream(stream, CompressionMode.Compress);
  18: 
  19:         StreamWriter writer = new StreamWriter(deflate);
  20: 
  21:         writer.Write(data.ToString());
  22:         writer.Close();
  23:     }
  24:     catch (IOException ex)
  25:     {
  26:         Console.WriteLine(ex.Message);
  27:     }
  28: }

باز کردن فایل از حالت فشرده

برای خواندن فایل‌های فشرده باید آنها را باز کرد. برای این کار نیز می‌توان از کلاس‌های GzipStream و DeflateStream استفاده کرد. ابتدا نحوه استفاده از کلاس GzipStream برای باز کردن فایل‌ها از حالت فشرده را توضیح می‌دهیم. به این نکته توجه کنید که از یک کلاس صحیح برای باز کردن یک فایل فشرده استفاده کنید. مثلاً اگر یک فایل با استفاده از Deflate فشرده شده است باید از DeflateStream برای باز کردن آن از حالت فشرده استفاده کنید تا با خطا مواجه نشوید.

   1: static void Main(string[] args)
   2: {
   3:     try
   4:     {
   5:         FileStream stream = new FileStream(@"C:compressedFile.txt",
   6:             FileMode.Open, FileAccess.Read);
   7: 
   8:         GZipStream gzip = new GZipStream(stream, CompressionMode.Decompress);
   9: 
  10:         StreamReader reader = new StreamReader(gzip);
  11:         string contents = reader.ReadToEnd();
  12:         reader.Close();
  13: 
  14:         Console.WriteLine(contents);
  15: 
  16:     }
  17:     catch (IOException ex)
  18:     {
  19:         Console.WriteLine(ex.Message);
  20:     }

مطمئن باشید که فایلی که شما دارید از حالت فشرده خارج می‌کنید اگر با کلاس GzipStream فشرده شده باشد و بخواهید آن را با استفاده از کلاس DeflateStream باز کنید با خطا مواجه می‌شوید. در خطوط 6-5 یک شیء FileStream ایجاد شده است که به یک فایل فشرده اشاره می‌کند. برای خواندن محتویات فایل از مقادیر FileMode.Open و FileAccess.Read در داخل سازنده استفاده می‌کنیم. در خط 8 یک شیء از GzipStream ایجاد می‌کنیم. تنها تفاوت تعیین مقدار compression mode در آرگومان دوم است. در این خط (خط 8) مقدار CompressionMode.Decompress را قرار می‌دهیم. از این مقدار (decompress) برای باز کردن فایل فشرده استفاده می‌شود. شیء GzipStream ایجاد شده از قبل را به شیء StreamReader در خط 10 ارسال می‌کنیم تا محتویات فایل را بخواند. در خط 11 از متد ReadToEnd() استفاده شده آیت که محتویات فایل فشرده را باز کرده و آن را به عنوان یک رشته بر می‌گرداند. در خط 14 نیز محتویات فایل، که از حالت فشرده خارج شده‌اند نمایش داده می‌شوند. اگر فایل را با استفاده از کلاس DeflateStream فشرده کرده‌اید باید از همین کلاس هم برای باز کردن آن استفاده نمایید. در مثال زیر به شما نشان می‌دهیم که چگونه یک فایل را با استفاده از کلاس DeflateStream از حالت فشرده خارج کنیم. برای این کار، دقیقاً مانند استفاده از کلاس GzipStream عمل می‌کنیم.

   1: static void Main(string[] args)
   2: {
   3:     try
   4:     {
   5:         FileStream stream = new FileStream(@"C:compressedFile.txt",
   6:             FileMode.Open, FileAccess.Read);
   7: 
   8:         DeflateStream deflate = new DeflateStream(stream, CompressionMode.Decompress);
   9: 
  10:         StreamReader reader = new StreamReader(deflate);
  11:         string contents = reader.ReadToEnd();
  12:         reader.Close();
  13: 
  14:         Console.WriteLine(contents);
  15: 
  16:     }
  17:     catch (IOException ex)
  18:     {
  19:         Console.WriteLine(ex.Message);
  20:     }

در این درس به شما نحوه فشرده کردن یک فایل ساده آموزش داده شد. شما می‌توانید از این کلاس‌ها برای فشرده سازی انواع مختلف فایل استفاده کنید.