Ouvrir un fichier en PHP
Pour lire un fichier partie par partie, nous allons avant tout devoir l’ouvrir. Pour ouvrir un fichier en PHP, nous allons utiliser la fonction fopen()
, abréviation de « file open » ou « ouverture de fichier » en français.
On va devoir passer le chemin relatif menant à notre fichier ainsi qu’un « mode » en arguments à cette fonction qui va alors retourner en cas de succès une ressource de pointeur de fichier, c’est-à-dire pour le dire très simplement une ressource qui va nous permettre de manipuler notre fichier.
Le mode choisi détermine le type d’accès au fichier et donc les opérations qu’on va pouvoir effectuer sur le fichier. On va pouvoir choisir parmi les modes suivants :
Mode d’ouverture | Description |
---|---|
r | Ouvre un fichier en lecture seule. Il est impossible de modifier le fichier. |
r+ | Ouvre un fichier en lecture et en écriture. |
a | Ouvre un fichier en écriture seule en conservant les données existantes. Si le fichier n’existe pas, le PHP tente de le créer. |
a+ | Ouvre un fichier en lecture et en écriture en conservant les données existantes. Si le fichier n’existe pas, le PHP tente de le créer. |
w | Ouvre un fichier en écriture seule. Si le fichier existe, les informations existantes seront supprimées. S’il n’existe pas, crée un fichier. |
w+ | Ouvre un fichier en lecture et en écriture. Si le fichier existe, les informations existantes seront supprimées. S’il n’existe pas, crée un fichier. |
x | Crée un nouveau fichier accessible en écriture seulement. Retourne false et une erreur si le fichier existe déjà. |
x+ | Crée un nouveau fichier accessible en lecture et en écriture. Retourne false et une erreur si le fichier existe déjà. |
c | Ouvre un fichier pour écriture seulement. Si le fichier n’existe pas, il sera crée. Si il existe, les informations seront conservées. |
c+ | Ouvre un fichier pour lecture et écriture. Si le fichier n’existe pas, il sera crée. Si il existe, les informations seront conservées. |
e | Le mode e est particulier et n’est pas toujours disponible. Nous n’en parlerons pas ici. |
Comme vous pouvez le constater, le choix du mode influe fortement sur les opérations que nous allons pouvoir réaliser sur le fichier en question.
Par exemple lorsqu’on ouvre un fichier en lecture seulement toute modification de ce fichier est impossible, ce qui n’est pas le cas si on choisit un mode permettant l’écriture dans ce fichier.
Notez par ailleurs qu’on ajoutera généralement la lettre b
au paramètre « mode » de fopen()
. Cela permet une meilleure compatibilité et évite les erreurs pour les systèmes qui différencient les fichiers textes et binaires comme Windows par exemple.
Lire un fichier partie par partie
PHP met à notre disposition plusieurs fonctions qui vont nous permettre de lire un fichier partie par partie :
- La fonction
fread()
; - La fonction
fgets()
; - La fonction
fgetc().
Lire un fichier jusqu’à un certain point avec fread()
La fonction fread()
(abréviation de « file read » ou « lecture de fichier » en français) va prendre en arguments le fichier renvoyé par fopen()
ainsi qu’un nombre qui correspond aux nombres d’octets du fichier qui doivent être lus.
Pour lire le fichier entièrement, on peut utiliser la fonction filesize()
en lui passant le nom du fichier qu’on souhaite lire en deuxième argument de fread()
. En effet, filesize()
renvoie la taille d’un fichier. Cela va donc nous permettre de lire entièrement un fichier à condition de commencer la lecture au début.
Illustrons cela avec un exemple concret. Pour cet exemple, je réutilise le fichier test.txt
créé dans la leçon précédente.
<!DOCTYPE html> <html> <head> <title>Cours PHP & MySQL</title> <meta charset="utf-8"> <link rel="stylesheet" href="cours.css"> </head> <body> <h1>Titre principal</h1> <?php $ressource = fopen('test.txt', 'rb'); echo fread($ressource, filesize('test.txt')); ?> <p>Un paragraphe</p> </body> </html>
Ici, on commence par utiliser fopen()
pour lire notre fichier et on récupère la ressource renvoyée par la fonction dans une variable $ressource
.
On passe ensuite le contenu de notre variable à fread()
et on lui demande de lire le fichier jusqu’au bout en lui passant la taille exacte du fichier obtenue avec filesize()
.
Finalement, on affiche le résultat renvoyé par fread()
grâce à une structure echo
.
Lire un fichier ligne par ligne avec fgets()
La fonction fgets()
va nous permettre de lire un fichier ligne par ligne. On va passer le résultat renvoyé par fopen()
en argument de fgets()
et à chaque nouvel appel de la fonction, une nouvelle ligne du fichier va pouvoir être lue.
On peut également préciser de manière facultative un nombre en deuxième argument de fgets()
qui représente un nombre d’octets. La fonction lira alors soit le nombre d’octets précisé, soit jusqu’à la fin du fichier, soit jusqu’à arriver à une nouvelle ligne (le premier des trois cas qui va se présenter). Si aucun nombre n’est précisé, fgets()
lira jusqu’à la fin de la ligne.
Notez que si on précise un nombre d’octets maximum à lire inférieur à la taille de notre ligne et qu’on appelle successivement fgets()
, alors la fin de la ligne courante sera lue lors du deuxième appel de fgets()
.
<!DOCTYPE html> <html> <head> <title>Cours PHP & MySQL</title> <meta charset="utf-8"> <link rel="stylesheet" href="cours.css"> </head> <body> <h1>Titre principal</h1> <?php $ressource = fopen('test.txt', 'rb'); //Lit les 30 premiers caractères du fichier echo 'Premier appel : ' .fgets($ressource, 30). '<br>'; //Lit le reste de la première ligne echo 'Deuxième appel : ' .fgets($ressource). '<br>'; //Lit la deuxième ligne du fichier echo 'Troisième appel : ' .fgets($ressource). '<br>'; ?> <p>Un paragraphe</p> </body> </html>
Lire un fichier caractère par caractère avec getc()
Dans certains cas, il va également être intéressant de lire un fichier caractère par caractère notamment pour récupérer un caractère en particulier ou pour arrêter la lecture lorsqu’on arrive à un certain caractère.
Pour faire cela, nous allons cette fois-ci utiliser la fonction fgetc()
. Cette fonction va s’utiliser exactement comme fgets()
, et chaque nouvel appel à la fonction va nous permettre de lire un nouveau caractère de notre fichier. Notez que les espaces sont bien entendus considérés comme des caractères.
<!DOCTYPE html> <html> <head> <title>Cours PHP & MySQL</title> <meta charset="utf-8"> <link rel="stylesheet" href="cours.css"> </head> <body> <h1>Titre principal</h1> <?php $ressource = fopen('test.txt', 'rb'); //Lit le premier caractère du fichier echo 'Premier appel : ' .fgetc($ressource). '<br>'; //Lit le deuxième caractère echo 'Deuxième appel : ' .fgetc($ressource). '<br>'; //Lit le troisième caractère echo 'Troisième appel : ' .fgetc($ressource). '<br>'; ?> <p>Un paragraphe</p> </body> </html>
Trouver la fin d’un fichier de taille inconnue
Dans ce cours, nous travaillons pour l’instant sur des exemples simples. Ici, par exemple, nous avons nous mêmes créé un fichier pour effectuer différentes opérations dessus.
En pratique, cependant, nous utiliserons généralement les fichiers pour stocker des informations non connues à l’avance. Dans ce cas-là, il est impossible de prévoir à l’avance la taille de ces fichiers et on risque donc de ne pas pouvoir utiliser les fonctions fgets()
et fgetc()
de manière optimale.
Il existe plusieurs moyens de déterminer la taille ou la fin d’un fichier. La fonction filesize()
, par exemple, va lire la taille d’un fichier. Dans le cas présent, cependant, nous cherchons plutôt à déterminer où se situe la fin d’un fichier (ce qui n’est pas forcément équivalent à la taille d’un fichier à cause de la place du curseur, notion que nous allons voir en détail par la suite).
La fonction PHP feof()
(« eof » signifie « end of the file » ou « fin du fichier ») va nous permettre de savoir si la fin d’un fichier a été atteinte ou pas. Dès que la fin d’un fichier est atteinte, cette fonction va renvoyer la valeur true
. Avant cela, elle renverra la valeur false
. On va donc pouvoir utiliser cette fonction pour boucler dans un fichier de taille inconnue.
<!DOCTYPE html> <html> <head> <title>Cours PHP & MySQL</title> <meta charset="utf-8"> <link rel="stylesheet" href="cours.css"> </head> <body> <h1>Titre principal</h1> <?php $res = fopen('test.txt', 'rb'); /*Tant que la fin du fichier n'est pas atteninte, c'est-à-dire *tant que feof() renvoie FALSE (= tant que !feof() renvoie TRUE) *on echo une nouvelle ligne du fichier*/ while(!feof($res)){ $ligne = fgets($res); echo 'La ligne "' .$ligne. '" contient ' .strlen($ligne). ' caractères <br>'; } ?> <p>Un paragraphe</p> </body> </html>
Ici, tant que la fin du fichier n’est pas atteinte, on affiche une nouvelle ligne de notre fichier et on calcule le nombre de caractères de la ligne grâce à la fonction strlen()
, abréviation de « string length » ou « longueur de la chaine » en français.
Notez qu’ici le fait de retourner à la ligne compte comme un caractère et que la fonctions fgets()
s’arrête après ce passage à la ligne. C’est la raison pour laquelle lorsqu’on compte le nombre de caractères de nos lignes, on a un caractère de plus que ce à quoi on pouvait s’attendre (sauf pour la dernière).
La place du curseur interne ou pointeur de fichier
La position du curseur (ou « pointeur de fichier ») va impacter le résultat de la plupart des manipulations qu’on va pouvoir effectuer sur les fichiers. Il est donc essentiel de toujours savoir où se situe ce pointeur et également de savoir comment le bouger.
Le curseur ou pointeur est l’endroit dans un fichier à partir duquel une opération va être faite. Pour donner un exemple concret, le curseur dans un document Word, dans un champ de formulaire ou lorsque vous effectuez une recherche Google ou tapez une URL dans votre navigateur correspond à la barre clignotante.
Ce curseur indique l’emplacement à partir duquel vous allez écrire votre requête ou supprimer un caractère, etc. Le curseur dans les fichiers va être exactement la même chose à la différence qu’ici on ne peut pas le voir visuellement.
Le mode d’ouverture choisi va être la première chose qui va influer sur la position du pointeur. En effet, selon le mode choisi, le pointeur de fichier va se situer à une place différente et va pouvoir ou ne va pas pouvoir être déplacé :
Mode utilisé | Position du pointeur de fichier |
---|---|
r / r+ | Début du fichier |
a / a+ | Fin du fichier |
w / w+ | Début du fichier |
x / x+ | Début du fichier |
c / c+ | Début du fichier |
Ensuite, vous devez également savoir que certaines fonctions vont modifier la place du curseur à chaque exécution. Cela va par exemple être le cas des fonctions fgets()
et fgetc()
qui servent à lire un fichier ligne par ligne ou caractère par caractère.
En effet, la première fois qu’on appelle fgets()
par exemple, le pointeur est généralement au début de notre fichier et c’est donc la première ligne de notre fichier est lue par défaut. Cependant, lors du deuxième appel à cette fonction, c’est bien la deuxième ligne de notre fichier qui va être lue.
Ce comportement est justement dû au fait que la fonction fgets()
déplace le pointeur de fichier du début de la première ligne au début de la seconde ligne dans ce cas précis.
Pour savoir où se situe notre pointeur de fichier, on peut utiliser la fonction ftell()
qui renvoie la position courante du pointeur. Nous allons devoir lui passer la valeur renvoyée par fopen()
pour qu’elle fonctionne correctement.
<!DOCTYPE html> <html> <head> <title>Cours PHP & MySQL</title> <meta charset="utf-8"> <link rel="stylesheet" href="cours.css"> </head> <body> <h1>Titre principal</h1> <?php $res = fopen('test.txt', 'rb'); while(!feof($res)){ echo 'Le pointeur est au niveau du caractère ' .ftell($res). '<br>'; $ligne = fgets($res); echo 'La ligne "' .$ligne. '" contient ' .strlen($ligne). ' caractères <br><br>'; } ?> <p>Un paragraphe</p> </body> </html>
Déplacer le curseur manuellement
Pour commencer la lecture d’un fichier à partir d’un certain point, ou pour écrire dans un fichier à partir d’un endroit précis ou pour toute autre manipulation de ce type, nous allons avoir besoin de contrôler la position du curseur. Pour cela, nous allons pouvoir utiliser la fonction fseek()
.
Cette fonction va prendre en arguments l’information renvoyée par fopen()
ainsi qu’un nombre correspondant à la nouvelle position en octets du pointeur.
La nouvelle position du pointeur sera par défaut calculée par rapport au début du fichier). Pour modifier ce comportement et faire en sorte que le nombre passé s’ajoute à la position courante du curseur, on peut ajouter la constante SEEK_CUR
en troisième argument de fseek()
.
Notez cependant que si vous utilisez les modes a
et a+
pour ouvrir votre fichier, utiliser la fonction fseek()
ne produira aucun effet et votre curseur se placera toujours en fin de fichier.
<!DOCTYPE html> <html> <head> <title>Cours PHP & MySQL</title> <meta charset="utf-8"> <link rel="stylesheet" href="cours.css"> </head> <body> <h1>Titre principal</h1> <?php $res = fopen('test.txt', 'rb'); echo 'Le pointeur est derrière le caractère ' .ftell($res). '<br>'; echo 'Le caractère ' .(ftell($res) + 1). ' est un ' .fgetc($res). '<br>'; echo 'Le pointeur est derrière le caractère ' .ftell($res). '<br>'; fseek($res, 20); echo 'Le pointeur est derrière le caractère ' .ftell($res). '<br>'; echo 'Le caractère ' .(ftell($res) + 1). ' est un ' .fgetc($res). '<br>'; echo 'Le pointeur est derrière le caractère ' .ftell($res). '<br>'; fseek($res, 40, SEEK_CUR); echo 'Le pointeur est derrière le caractère ' .ftell($res). '<br>'; echo 'Le caractère ' .(ftell($res) + 1). ' est un ' .fgetc($res). '<br>'; ?> <p>Un paragraphe</p> </body> </html>
Fermer un fichier
Pour fermer un fichier en PHP, nous utiliserons cette fois la fonction fclose()
.
On va une nouvelle fois passer le résultat renvoyé par fopen()
en argument de cette fonction.
Notez que la fermeture d’un fichier n’est pas strictement obligatoire. Cependant, cela est considéré comme une bonne pratique : cela évite d’user inutilement les ressources de votre serveur.
<!DOCTYPE html> <html> <head> <title>Cours PHP & MySQL</title> <meta charset="utf-8"> <link rel="stylesheet" href="cours.css"> </head> <body> <h1>Titre principal</h1> <?php $res = fopen('test.txt', 'rb'); echo fread($res, filesize('test.txt')); fclose($res); ?> <p>Un paragraphe</p> </body> </html>
Bonjour,
Excusez moi de vous poser cette question :
avec :
//Lit les 30 premiers caractères du fichier
echo ‘Premier appel : ‘ .fgets($ressource, 30). »;
affiche :
Dans cette première section,
soit 27 caractères (ou octets) et non pas 30 comme l’argument du paramètre de fgets….
Du coup je ne comprend pas l’ecart.
Désolé, je ne suis pas du genre à poser des questions sans avoir cherché, et là je seche…
Amicalement,
Bonjour,
Le « è » correspond à 2 octets en utf-8. Les espaces et la virgule représentent un octet chacun. En faisant l’hypothèse qu’une espace est comptée dans le calcul après la virgule, on arrive bien à 30.
Amicalement,
Rebonjour !!!
J’ai trouvé : cela tombe juste avec mes essais si j’enregistre le fichier texte en encodage AINSI et non pas utf-8 (sur mes essais)…..
(je ne comprend pas pourquoi mais c’est déja mieux 🙂 )