I. Introduction▲
Cet article présente la compression de fichiers avec la bibliothèque Zlib de Jean-loup Gailly et Mark Adler. Les fichiers compressés avec cet algorithme portent l'extension gz. La bibliothèque est téléchargeable ici : http://www.gzip.org/zlib/
II. Accès aux fichiers▲
Pour enregistrer ou lire un fichier compressé, il faut utiliser les fonctions gzopen() et gzclose() sur le même modèle que les fonctions standards fopen() et fclose(). Ces deux fonctions retournent un pointeur de fichier qui devra être passé en argument aux autres fonctions de traitement.
II-A. Ouverture▲
Les modes d'ouverture des fichiers sont les mêmes qu'avec la fonction standard fopen().
Mode |
Description |
---|---|
r |
ouverture en lecture seule, pointeur placé en début de fichier |
r+ |
ouverture en lecture et écriture, pointeur placé en début de fichier |
w |
ouverture en écriture seule, pointeur placé en début de fichier, écrase le contenu du fichier, si le fichier n'existe pas, on tente de le créer |
w+ |
ouverture en lecture et écriture, pointeur placé en début de fichier, écrase le contenu du fichier, si le fichier n'existe pas, on tente de le créer |
a |
ouverture en lecture seule, pointeur placé en fin de fichier, si le fichier n'existe pas, on tente de le créer |
a+ |
ouverture en lecture et écriture, pointeur placé en fin de fichier, si le fichier n'existe pas, on tente de le créer |
Ce mode peut être complété par le niveau de compression (en écriture seulement) entier compris entre 0 et 9, exemple : w5. Un autre suffixe peut être ajouté pour indiquer une heuristique pour filtrer les données : f, exemple : w5f. Le suffixe h permet de n'activer que la compression de Huffman, exemple : w5h.
Syntaxe d'ouverture de fichier :
resource gzopen(string $filename
,
string $mode
,
int $use_include_path
)
Exemple d'ouverture de fichier en lecture :
$gz
=
gzopen("
archive.gz
"
,
"
r
"
);
Si le paramètre optionnel $use_include_path est passé à 1, alors la fonction gzopen() recherchera le fichier dans le répertoire défini par la directive de configuration include_path du php.ini. La fonction gzopen() retourne un entier valant false en cas d'erreur.
II-B. Fermeture▲
Syntaxe de fermeture de fichier :
int gzclose
(resource $gz
)
Exemple de fermeture de fichier :
gzclose
($gz
);
La fonction gzclose() retourne un entier valant true si succès, ou false en cas d'erreur.
III. Accès aux données▲
Les accès au contenu des fichiers ouverts dépendent de leur mode d'ouverture. On peut lire avec gzread() un fichier ouvert en lecture, et écrire avec gzwrite() dans un fichier ouvert en écriture.
III-A. Lecture▲
III-A-1. Par bloc▲
Syntaxe :
string gzread
(resource $gz
,
int $length
)
Exemple :
$str
=
gzread
($gz
,
1024
);
La fonction gzread() retourne une chaîne de caractères en décompressant à la volée le fichier spécifié. La lecture commence à la position courante et se termine après $length caractères décompressés lus, ou en fin de fichier si celle-ci a été atteinte.
III-A-2. Par ligne▲
Syntaxe :
string gzgets
(resource $gz
,
int $length
)
Retourne une chaîne décompressée de taille maximale $length - 1. La lecture s'arrête si un saut de ligne ou une fin de fichier est rencontré(e). Permet une lecture ligne par ligne du fichier.
III-A-3. Par ligne, sans balise▲
Syntaxe :
string gzgetss
(resource $gz
,
int $length
[,
string $allowable_tags
]
)
Identique à gzgets(), sauf que toutes les balises HTML et PHP sont automatiquement supprimées. Le paramètre optionnel $allowable_tags permet de lister les balises à conserver.
III-A-4. Par caractère▲
Syntaxe :
string gzgetc
(resource $gz
)
Retourne une chaîne décompressée contenant un seul caractère. Permet une lecture caractère par caractère du fichier. Retourne false si la fin du fichier est atteinte.
III-A-5. Tout le fichier dans un tableau▲
Syntaxe :
Exemple :
Identique à la fonction file(), mais décompresse à la volée le contenu du fichier, si celui-ci est compressé (cette fonction peut donc servir à lire des fichiers non compressés). Retourne un tableau dont chaque élément est une ligne du fichier $filename. Le paramètre optionnel $use_include_path passé à 1 permet de rechercher le fichier dans le répertoire défini par la directive de configuration include_path du php.ini.
contrairement aux autres fonctions, cette fonction prend pour paramètre le nom du fichier et pas un pointeur créé par gzopen(). Il n'est donc pas utile d'ouvrir le fichier au préalable.
III-A-6. Tout le fichier à l'écran▲
Syntaxe :
int readgzfile(string $filename
[,
int $use_include_path
]
)
Exemple :
readgzfile('
archive.gz
'
);
Identique à la fonction readfile(), mais décompresse à la volée le contenu du fichier, si celui-ci est compressé (cette fonction peut donc servir à lire des fichiers non compressés). Lit le fichier et l'affiche directement dans la sortie standard. Retourne le nombre d'octets décompressés. Le paramètre optionnel $use_include_path passé à 1 permet de rechercher le fichier dans le répertoire défini par la directive de configuration include_path du php.ini.
contrairement aux autres fonctions, cette fonction prend pour paramètre le nom du fichier et pas un pointeur créé par gzopen(). Il n'est donc pas utile d'ouvrir le fichier au préalable.
III-B. Écriture▲
Syntaxe d'écriture :
int gzwrite
(resource $gz
,
string $str
[,
int $length
]
)
Exemples d'écriture :
2.
gzwrite
($gz
,
$str
);
gzwrite
($gz
,
$str
,
1024
);
La fonction gzwrite() compresse la chaîne $str à la volée et écrit le résultat dans le fichier spécifié. L'écriture débute à la position courante du fichier et s'arrête après $length caractères non compressés écrits ou dès que la fin de la chaîne $str a été atteinte.
gzputs() est un alias de gzwrite().
III-C. Position du pointeur interne▲
III-C-1. Position du pointeur▲
Syntaxe :
int gztell
(resource $gz
)
Identique à ftell() : retourne la position courante du pointeur de lecture dans le fichier.
III-C-2. Déplacement du pointeur▲
Syntaxe :
int gzseek
(resource $gz
,
int $offset
)
Semblable à fseek(). Déplace de $offset octets dans le fichier. S'il est ouvert en écriture, seuls les déplacements vers l'avant sont possibles : il compresse une série de zéros jusqu'à la position indiquée. Retourne 0 si succès, -1 sinon.
III-C-3. Retour au début▲
Syntaxe :
int gzrewind
(resource $gz
)
Identique à rewind(). Replace le pointeur interne au début du fichier. Utile pour relire un fichier. Retourne 0 en cas d'échec.
III-C-4. Fin de fichier▲
Syntaxe :
int gzeof
(resource $gz
)
Identique à feof(). Retourne true si la fin du fichier a été atteinte, false sinon.
IV. Compression à la volée▲
IV-A. Compression▲
Syntaxe de compression :
string gzcompress(string $str
[,
int $level
]
)
Exemples de compression :
2.
$str
=
gzcompress($str
,
9
);
$str
=
gzcompress($str
);
La fonction gzcompress() compresse la chaîne $str et retourne le résultat. L'argument optionnel $level définit la qualité de la compression, ce doit être un nombre entier positif compris entre 0 (pas de compression) et 9 (compression maximale).
cette fonction ne doit pas être utilisée pour créer un fichier archive, car ce dernier doit comporter des entêtes que seules les fonctions gzencode() et gzopen() créent.
IV-B. Décompression▲
Syntaxe de décompression :
string gzuncompress(string $str
[,
int $length
]
)
Exemples de décompression :
2.
$str
=
gzuncompress($str
,
100
);
$str
=
gzuncompress($str
);
La fonction gzuncompress() décompresse la chaîne $str compressée par gzcompress() et retourne le résultat. Cette fonction retourne false si la chaîne décompressée est plus de 256 fois supérieure à la chaîne compressée $str, ou de taille supérieure à $length caractères.
IV-C. Compression indépendante▲
Syntaxe :
string gzencode(string $data
[,
int $level
[,
int $encoding_mode
]
]
)
Exemple :
Retourne une chaîne résultant de la compression de $data ou false si échec. Le paramètre optionnel $level spécifie le niveau de compression (entre 0 et 9). Le paramètre optionnel $encoding_mode permet de spécifier la constante FORCE_GZIP (par défaut) ou bien FORCE_DEFLATE, cette dernière produit une chaîne compressée réduite sans la somme de contrôle finale CRC32.
Contrairement à gzcompress(), cette fonction produit tous les entêtes nécessaires à la création d'un fichier avec les fonctions standards.
V. Exemples▲
V-A. Compression d'un fichier du serveur▲
Le script ci-dessous procède comme suit :
- lecture du fichier source avec les fonctions standards fopen() et fread() ;
- compression du contenu de ce fichier avec gzencode() ;
- création d'un nouveau fichier avec les fonctions standards, dont le contenu est le résultat de la compression du premier fichier ;
- affichage à l'écran du grain de la compression en valeur absolue et en valeur relative.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
<?php
/******************************************
* COMPRESSION D'UN FICHIER DU SERVEUR
*
* - lecture des données originales
* - compression avec gzencode()
* - écriture des données compressées
* - affichage du gain de la compression
*
*
29
mai
2003
, Hugo ETIEVANT
* http://cyberzoide.developpez.com/php4/
*******************************************/
// nom et chemin du fichier à compresser
$filename
=
'./gz.pdf'
;
// ouverture du fichier à compresser
if
($fp
=
fopen($filename
,
"rb"
)) {
// lecture du contenu
$size1
=
filesize($filename
);
$data
=
fread($fp
,
$size1
);
// fermeture
fclose($fp
);
// compression des données
$gzdata
=
gzencode($data
,
9
);
// ouverture et création du fichier compressé
if
($fp
=
fopen($filename
.
'.gz'
,
'wb'
)) {
// écriture des données compressées
fwrite($fp
,
$gzdata
);
// fermeture
fclose($fp
);
// calcul gain de la compression
$size2
=
filesize($filename
.
'.gz'
);
$diff
=
$size1
-
$size2
;
$pc
=
round($diff
/
$size1
*
100
,
2
);
echo "Gain de la compression :
$diff
octets soit
$pc
%."
;
}
else
{
echo "Impossible d'ouvrir
$filename
.gz en écriture."
;
}
}
else
{
echo "Impossible d'ouvrir
$filename
en lecture."
;
}
?>
Affiche ceci :
Gain de la compression : 17909 octets soit 32.63 %.
V-B. Affichage du contenu d'un fichier compressé▲
Le script ci-dessous procède comme suit :
- ouverture d'un fichier compressé avec gzopen() en mode lecture binaire (« rb ») ;
- lecture et décompression à la volée du contenu par bloc de 1024 avec gzread() tant que la fin de fichier n'est pas vérifiée (gzeof()) ;
- affichage du texte à l'écran.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
<?php
/******************************************
* LECTURE D'UN FICHIER COMPRESSE
*
*
29
mai
2003
, Hugo ETIEVANT
* http://cyberzoide.developpez.com/php4/
*******************************************/
// nom et chemin du fichier compressé
$filename
=
'./gz.txt.gz'
;
// ouverture du fichier compresser à lire
if
($gz
=
gzopen($filename
,
"rb"
)) {
// tant qu'on n'a pas atteint la fin du fichier
while
(!
gzeof($gz
)) {
// lecture et décompression à la volée
$text
.=
gzread($gz
,
1024
);
}
// affichage du texte
echo $text
;
}
else
{
echo "Impossible d'ouvrir
$filename
en lecture."
;
}
?>
Je remercie Le vieux pour la relecture et ses suggestions de corrections orthographiques.