|
Il .NET Framework consente la compressione di dati in modo piuttosto semplice. All'interno del namespace System.IO.Compression, infatti,
sono esposte due classi, di nome DeflateStream e GZipStream. Entrambe hanno lo stesso funzionamento e combinano l'algoritmo di compressione
LZ77 con la codifica di Huffman. Tuttavia, non sono "indipendenti", poiché devono reggersi sul supporto di un altro stream, che rappresenta
la vera connessione con il file da comprimere/decomprimere. Il codice da usare è questo:
Imports System.IO
Imports System.IO.Compression
Module Module1
Sub Main()
'I percorsi del file da comprimere e di quello compresso
Dim File, CompressedFile As String
'Lo stream che legge i dati da File
Dim Input As FileStream
'Lo stream di scrittura associato al file compresso
Dim Output As FileStream
'Lo stream compresso che scrive i dati codificati per mezzo
'dell'output stream
Dim Zipped As DeflateStream
Console.WriteLine("Inserire il percorso del file da compriemere:")
File = Console.ReadLine
Console.WriteLine("Inserire il percorso in cui salvare i dati compressi:")
CompressedFile = Console.ReadLine
'Controlla che il file esista
If Not IO.File.Exists(File) Then
Console.WriteLine("File inesistente!")
Exit Sub
End If
'Inizializza lo stream di input
Input = New FileStream(File, IO.FileMode.Open)
'Inizializza lo stream di output
Output = New FileStream(CompressedFile, IO.FileMode.Create)
'Inizializza lo zipper
Zipped = New DeflateStream(Output, CompressionMode.Compress)
'Buffer temporaneo che contiene pacchetti di dati
Dim Buffer(4095) As Byte
'Legge i bytes a blocchi di 4KiB
For I As Int64 = 0 To Input.Length - 1 Step 4096
If Input.Length - I >= 4096 Then
Input.Read(Buffer, 0, 4096)
Else
Input.Read(Buffer, 0, Input.Length - I)
End If
'Li scrive sullo stream compresso
Zipped.Write(Buffer, 0, Buffer.Length)
Next
'Trasferisce dati compressi sullo stream
Zipped.Flush()
'Quindi chiude tutti gli stream
Zipped.Close()
Output.Close()
Input.Close()
'Alla fine calcola la compressione totale
'Ottiene la dimensione iniziale del file
Dim StartSize As Int64 = FileLen(File)
'E quella finale del file compresso
Dim EndSize As Int64 = FileLen(CompressedFile)
Console.WriteLine("Compressione totale: {0:N2}%", _
100 - (EndSize * 100 / StartSize))
Console.ReadKey()
End Sub
End Module
Potete provare il programma con il file assembly.txt fornito nell'ultima lezione sulla Reflection, la cui compressione sarà circa
dell'85%. Bisogna notare che, alla fine del processo, i dati sono sì compressi, ma nessun programma è capace di aprirli se non
quello che si è scritto: sebbe l'algoritmo usato sia quello dei file *.zip, non vengono salvate le informazioni necessarie a strutturare
lo stream in maniera standard così da poter essere letto normalmente. Nella maggior parte dei casi, questo è un vantaggio: il
mio programma Tot Compressor (nella sezione download), usa proprio queste tecniche, ma crea anche una nuova composizione interna per i file
in modo da riuscire ad estrapolarne i dati e a stipare più files in uno solo.
Per decomprimere lo stesso file, si agisce in maniera inversa: l'output sarà lo stream del file decompresso, l'input quello compresso
e il DeflateStream avrà modalità di compressione Decompress. |
|