MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Arhivarea și comprimarea fișierelor

Pe lângă clasele de citire și scriere, .NET oferă și clase care permit comprimarea fișierelor și apoi restaurarea lor în starea inițială.

Aceste clase sunt ZipFile, DeflateStream și GZipStream, care se află în spațiul de nume System.IO.Compression și implementează algoritmi de comprimare precum Deflate sau GZip.

GZipStream și DeflateStream

Pentru a crea un obiect GZipStream, se poate folosi unul dintre constructorii săi:

  • GZipStream(Stream stream, CompressionLevel level): stream reprezintă datele, iar level setează nivelul de comprimare
  • GZipStream(Stream stream, CompressionMode mode): mode indică dacă datele vor fi comprimate sau restaurate și poate avea două valori:

CompressionMode.Compress: datele sunt comprimate.

CompressionMode.Decompress: datele sunt restaurate.

Dacă datele sunt comprimate, stream indică fluxul datelor care urmează să fie arhivate. Dacă datele sunt restaurate, stream indică fluxul în care vor fi transferate datele restaurate.

  • GZipStream(Stream stream, CompressionLevel level, bool leaveOpen): parametrul leaveOpen indică dacă fluxul stream trebuie lăsat deschis după ce obiectul GZipStream este eliminat. Dacă valoarea este true, fluxul rămâne deschis
  • GZipStream(Stream stream, CompressionMode mode, bool leaveOpen)

Pentru a gestiona comprimarea/restaurarea datelor, GZipStream oferă o serie de metode esențiale:

  • void CopyTo(Stream destination): copiază toate datele în fluxul destination
  • Task CopyToAsync(Stream destination): versiunea asincronă a metodei CopyTo
  • void Flush(): curăță bufferul, scriind toate datele în fișier
  • Task FlushAsync(): versiunea asincronă a metodei Flush
  • int Read(byte[] array, int offset, int count): citește datele din fișier într-un array de bytes și returnează numărul de bytes citite. Primește trei parametri:

- array: array-ul de bytes în care vor fi plasate datele citite din fișier.

- offset: deplasarea în bytes în array-ul array, în care vor fi plasate bytes-ii citiți.

- count: numărul maxim de bytes care urmează să fie citiți. Dacă în fișier există mai puțini bytes, aceștia vor fi citiți toți.

  • Task<int> ReadAsync(byte[] array, int offset, int count): versiunea asincronă a metodei Read
  • long Seek(long offset, SeekOrigin origin): setează poziția în flux cu o deplasare de numărul de bytes specificat în parametrul offset
  • void Write(byte[] array, int offset, int count): scrie datele din array-ul de bytes în fișier. Primește trei parametri:

- array: array-ul de bytes din care datele vor fi scrise în fișier.

- offset: deplasarea în bytes în array-ul array, de unde începe scrierea bytes-ilor în flux.

- count: numărul maxim de bytes care urmează să fie scriși.

  • Task WriteAsync(byte[] array, int offset, int count): versiunea asincronă a metodei Write.

Să vedem un exemplu de utilizare a clasei GZipStream:

using System.IO.Compression;

string sourceFile = "book.pdf"; // fișierul sursă
string compressedFile = "book.gz"; // fișierul comprimat
string targetFile = "book_new.pdf"; // fișierul restaurat

// crearea fișierului comprimat
await CompressAsync(sourceFile, compressedFile);
// citirea din fișierul comprimat
await DecompressAsync(compressedFile, targetFile);

async Task CompressAsync(string sourceFile, string compressedFile)
{
   // flux pentru citirea fișierului sursă
   using FileStream sourceStream = new FileStream(sourceFile, FileMode.OpenOrCreate);
   // flux pentru scrierea fișierului comprimat
   using FileStream targetStream = File.Create(compressedFile);

   // fluxul de comprimare
   using GZipStream compressionStream = new GZipStream(targetStream, CompressionMode.Compress);
   await sourceStream.CopyToAsync(compressionStream); // copiem bytes dintr-un flux în altul

   Console.WriteLine($"Comprimarea fișierului {sourceFile} a fost finalizată.");
   Console.WriteLine($"Dimensiunea originală: {sourceStream.Length}  dimensiunea comprimată: {targetStream.Length}");
}

async Task DecompressAsync(string compressedFile, string targetFile)
{
   // flux pentru citirea din fișierul comprimat
   using FileStream sourceStream = new FileStream(compressedFile, FileMode.OpenOrCreate);
   // flux pentru scrierea fișierului restaurat
   using FileStream targetStream = File.Create(targetFile);
   // fluxul de decomprimare
   using GZipStream decompressionStream = new GZipStream(sourceStream, CompressionMode.Decompress);
   await decompressionStream.CopyToAsync(targetStream);
   Console.WriteLine($"Fișierul a fost restaurat: {targetFile}");
}

În acest exemplu, se presupune că în folderul cu programul se află fișierul book.pdf, care va fi arhivat.

Metoda CompressAsync primește numele fișierului sursă care trebuie arhivat și numele viitorului fișier comprimat.

Mai întâi, se creează un flux pentru citirea din fișierul sursă - FileStream sourceStream. Apoi se creează un flux pentru scrierea în fișierul comprimat - FileStream targetStream. Fluxul de arhivare GZipStream compressionStream este inițializat cu fluxul targetStream și, cu ajutorul metodei CopyToAsync(), primește date din fluxul sourceStream.

Metoda DecompressAsync efectuează operația inversă de restaurare a fișierului comprimat în starea sa inițială. Ea primește ca parametri căile către fișierul comprimat și fișierul restaurat.

Aici, mai întâi se creează un flux pentru citirea din fișierul comprimat FileStream sourceStream, apoi un flux pentru scrierea în fișierul restaurat FileStream targetStream. La final, se creează fluxul GZipStream decompressionStream, care, cu ajutorul metodei CopyToAsync(), copiază datele restaurate în fluxul targetStream.

Pentru a specifica scopul fluxului GZipStream - comprimare sau restaurare - în constructorul său se transmite parametrul CompressionMode, care poate lua două valori: Compress și Decompress.

Exemplu de ieșire în consolă:

Comprimarea fișierului book.pdf a fost finalizată.
Dimensiunea originală: 3235353  dimensiunea comprimată: 2574401
Fișierul a fost restaurat: book_new.pdf

Dacă dorim să folosim altă clasă de comprimare, cum ar fi DeflateStream, putem pur și simplu să înlocuim în cod referințele la GZipStream cu DeflateStream, fără a modifica restul codului. Utilizarea lor este identică.

Totuși, folosirea acestor clase are unele limitări; de exemplu, putem comprima doar un singur fișier. Pentru arhivarea unui grup de fișiere, este mai bine să utilizăm alte instrumente, cum ar fi ZipFile.

Clasa statică ZipFile

Clasa statică ZipFile din spațiul de nume System.IO.Compression oferă funcționalități suplimentare pentru crearea arhivelor. Aceasta permite crearea unei arhive din directoare. Principalele sale metode sunt:

  • void CreateFromDirectory(string sourceDirectoryName, string destinationFileName): arhivează un folder de la calea sourceDirectoryName într-un fișier cu numele destinationFileName
  • void ExtractToDirectory(string sourceFileName, string destinationDirectoryName): extrage toate fișierele din fișierul zip sourceFileName în directorul destinationDirectoryName

Ambele metode au mai multe versiuni supraîncărcate. Să vedem un exemplu de utilizare:

using System.IO.Compression;

string sourceFolder = "D://test/"; // folderul sursă
string zipFile = "D://test.zip"; //

fișierul comprimat
string targetFolder = "D://newtest"; // folderul în care va fi extras fișierul

ZipFile.CreateFromDirectory(sourceFolder, zipFile);
Console.WriteLine($"Folderul {sourceFolder} a fost arhivat în fișierul {zipFile}");
ZipFile.ExtractToDirectory(zipFile, targetFolder);

Console.WriteLine($"Fișierul {zipFile} a fost extras în folderul {targetFolder}");

În acest exemplu, folderul "D://test/" este arhivat în fișierul test.zip folosind metoda ZipFile.CreateFromDirectory. Apoi, metoda ZipFile.ExtractToDirectory() extrage acest fișier în folderul "D://newtest" (dacă acest folder nu există, va fi creat).

← Lecția anterioară Lecția următoare →