lundi 10 décembre 2012

Compression avec GZip.

Nous allons voir aujourd'hui la compression de fichier avec Gzip. Gzip un algorithme standard pour la compression et la décompression de fichiers sans perte. Le format inclut une valeur de contrôle de redondance cyclique pour détecter les données endommagées.

 
#Text à compresser.
$citation1 = "Depuis le 24 mars 2009, Windows PowerShell 1.0 pour Windows XP et Vista est distribué comme une mise à jour logicielle facultative par le service Windows Update de Microsoft. Il est intégré nativement dans Windows 7 en version 2.0[1]. Cette version propose une console d'édition de script intégré appelé Windows PowerShell ISE (pour Integrated Scripting Environment en anglais) qui apporte une solution alternative a l'outil PowerGUI Script Editor développé par la société Quest Software. Comme son homologue Windows PowerShell ISE présente un environnement graphique qui permet l’édition de script avec coloration syntaxique, affichage des numéros de ligne, débogueur intégré et aide en ligne." 

#Laissez ces deux lignes en commentaire dans un premier temps.
#$citation1 = $citation1 + $citation1
#$citation1 = $citation1 + $citation1

#Affichage des données à compresser.
Write-Host "----------------------"
Write-Host $citation1

##################
# Compression
##################

#Création d'un objet "MemoryStream" pour stocker les données compressées.
$ms = New-Object System.IO.MemoryStream

#Création de l'objet GZipStream.
#J'affecte la zone mémoire $ms pour le traitement et le flag pour la compression.
$gz = New-Object System.IO.Compression.GZipStream($ms, [System.IO.Compression.CompressionMode]::Compress)

#Création d'un flux écriture vers mon objet GZip.
$wm = New-Object System.IO.StreamWriter($gz)

#Envoie le texte dans le flux de données à compresser.
$wm.write($citation1)

#La compression est terminée, je peux vider le flux d'écriture, et libérer l'objet GZip.
$wm.flush()
$gz.close()

#Les données compressées sont stockées dans $ms.
#je vais convertir tout ça en "String" pour pouvoir l'afficher ensuite.
$mb = $ms.ToArray()
$citation2 = [System.Convert]::ToBase64String($mb)

#Affiche le résultat.
Write-Host "-------------------------------------"
Write-Host $citation2
Write-Host "-------------------------------------"

####################
# Décompression.
####################

#Reconvertir les données.
$in = [System.Convert]::FromBase64String($citation2)

#Création d'un objet "MemoryStream".
$ms = New-Object System.IO.MemoryStream

#Ecrit les données compressées dans le flux mémoire.
$ms.Write($in, 0, $in.Length)

#Repositionne le pointeur de lecture au début du flux.
$r = $ms.Seek(0,0)

#Création de l'objet GZip.
#J'affecte la zone mémoire contenant les données et le flag "Decompression".
$gz = New-Object System.IO.Compression.GZipStream($ms, [System.IO.Compression.CompressionMode]::Decompress)

#Création d'un flux lecture depuis mon objet GZip.
$rm = New-Object System.IO.StreamReader($gz)

#Lecture des données.
$citation3 = $rm.readtoend()

#Ferme l'objet GZip
$gz.close()

#Affiche les données décompressées.
Write-Host $citation3

#Résumé final.
Write-Host "--------------------------------"
Write-Host "Original    : " $citation1.length
Write-Host "Compressé   : " $citation2.length
Write-Host "Décompressé : " $citation3.length

#Fin.

Vous devez obtenir le résultat suivant :
Taille originale    :  694
Taille compressée   :  756
Taille décompressée :  694

La première chose que l'on remarque c'est que là taille du texte compressé est plus grande que la taille originale. En fait, lorsque le texte original est trop petite, la compression est inefficace. Maintenant nous allons retirer le # devant les deux lignes "$citation1 = $citation1 + $citation1" pour augmenter la taille du texte à traiter :
Taille originale    :  2776
Taille compressée   :  796
Taille décompressée :  2776

Cette fois la compression est efficace. Le texte compressé fait 28% de sa taille initiale.