Les fichiers
Dernière mise à jour le 23 septembre 2025
Ouverture d'un fichier
La plupart des opérations sur un fichier nécessitent que celui soit préalablement ouvert.
On utilise la fonction fopen() dont la syntaxe est :
resource|false descripteur =
fopen(string nom_fichier, string mode [,bool utiliser_include_path]);
Paramètres :
-
Le premier paramètre est le nom du fichier, incluant éventuellement le chemin d'accès correspondant.
-
Le deuxième paramètre est le mode d'ouverture du fichier (voir plus loin).
-
Le troisième paramètre est optionnel et rarement utilisé. Il spécifie si on veut que le fichier soit recherché dans le "include_path" (sa valeur est
FALSEpar défaut).
Le "include_path"
include_path est une directive de configuration qui spécifie le chemin à utiliser pour trouver le fichier à ouvrir.
Cette directive est utilisée par les instructions require et include, de même que par les fonctions fopen(), file(), readfile() et file_get_contents().
Le format du chemin est identique à la variable d'environnement système PATH, soit une liste de répertoires séparés par deux points (:) sous Linux ou par un point-virgule (;) sous Windows.
Ceci est une valeure possible du "include_path" :
.:/usr/share/php:/autre/dossier
Dans cet exemple, les fichiers seront d'abord recherchés dans le répertoire courant ("."), puis dans /usr/share/php, puis dans /autre/dossier.
Le "include_path" est défini dans le fichier php.ini et on peut en vérifier la valeur à l'aide de la fonction phpinfo().
Mode d'ouverture
Le tableau suivant présente les principales valeurs possibles du deuxième paramètre de la fonction fopen() :
| Mode | Signification |
|---|---|
| r | Lecture seulement. |
| r+ | Lecture et écriture. À la différence de "w+", le fichier doit exister. |
| w | Écriture seulement. Si le fichier existe déjà, son contenu est écrasé. Dans le cas contraire, le fichier est créé. |
| w+ | Même chose que "w", mais permet aussi la lecture. |
| a | Écriture seulement avec ajout des données à la fin du fichier. Si le fichier n'existe pas encore, il est créé. |
| a+ | Même chose que "a", mais permet aussi la lecture. |
Remarque : même si lire et écrire dans un même fichier (sans fermeture et réouverture entre les opétations) est possible, l'opération est délicate étant donné qu'elle exige le repositionnement du pointeur de fichier.
Exemples d'ouverture d'un fichier :
// ouverture en lecture seulement du fichier "proverbes.txt" dans le sous-répertoire
// "textes" du répertoire courant
$fich = fopen("textes/proverbes.txt", "r");
// même chose que l'exemple précédent, mais le fichier est recherché dans le "include_path"
$fich = fopen("textes/proverbes.txt", "r", TRUE);
// ouverture en écriture du fichier "/home/utilisateur/public_html/donnees/clients.csv"$chemin = "/home/utilisateur/public_html/donnees/clients.csv";$chemin = "$_SERVER['CONTEXT_DOCUMENT_ROOT']/donnees/clients.csv"; $data = fopen($chemin, "w");
La variable $_SERVER['CONTEXT_DOCUMENT_ROOT'] contient le chemin du répertoire Web de l'usager. Cette variable devrait toujours être utilisée à la place du chemin absolu.
// ouverture du fichier "/home/utilisateur/commandes/commandes.txt"
$chemin = "$_SERVER['CONTEXT_DOCUMENT_ROOT']/../commandes/commandes.txt"
$fich_commandes = fopen($chemin, "a");
Problèmes d'ouverture
Les deux erreurs les plus fréquentes sont :
- un fichier inexistant;
- des droits d'accès inadéquats.
Lorsque l'appel à la fonction fopen() échoue, celle-ci renvoie la valeur FALSE.
Exemple :
$fich = fopen("fichiers/blabla.txt", "r");
// si l'ouverture du fichier est possible
if ($fich !== false) {
...
}
L'échec peut entraîner (selon de la configuration de PHP sur le serveur) l'affichage d'un message déplaisant :
On peut traiter l'erreur avec plus de convivialité en supprimant le message d'erreur PHP (avec le caractère @) et en générant notre propre message.
Exemple :
@ $fich = fopen("fichiers/blabla.txt", "r");
if ($fich !== false) {
...
} else {
echo <<<FIN
Votre commande ne peut être traitée<br>
Veuillez S.V.P. essayer plus tard
FIN;
exit(1); // termine immédiatement le programme
}
Droits d'accès
Puisque notre but principal est de créer des applications Web, toutes les opérations sur nos fichiers se feront à partir d'un script invoqué depuis un navigateur Web.
Vous devrez donc maintenant tenir compte du fait suivant : pour des raisons de sécurité, toutes les opérations sur les fichiers effectuées à partir du Web sont effectuées dans le système de fichiers du serveur par un même usager, soit www-data.
Supposez par exemple que l'usager bob a écrit un script qui doit ajouter des données au fichier donnees/data.txt. Pour le serveur, lorsqu'un internaute exécute le script, la ligne suivante :
$fich = fopen("donnees/data.txt", "a");
n'est pas exécutée par l'usager bob, mais par l'usager www-data. L'usager virtuel dont le nom est www-data (ou le groupe du même nom selon le réglage des permissions) doit donc avoir accès en écriture au fichier donnees/data.txt.
AVERTISSEMENT : Faites par vous-mêmes les manipulations suivantes. Relisez au besoin le texte si quelque chose ne fontionne pas. Développez votre autonomie. Dans 18 mois vous serez en stage à faire des choses dix fois plus compliquées. Vous êtes capables, mais à condition de faire l'effort nécessaire.
Puisque plusieurs d'entre vous ne sont pas (pour l'instant) très confortables en Linux, voici une procédure simple à utiliser si votre application contient un script qui doit écrire dans un fichier :
- créez dans le répertoire public_html le sous-répertoire (ex : donnees) qui contiendra le fichier devant être accessible en écriture (vous pouvez utiliser FileZilla pour toutes ces manipulations);
-
donnez (temporairement) à ce sous-répertoire les droits d'accès correspondant au code
777(tous les droits pour toutes les catégories d'utilisateurs); -
exécutez (via le Web) un script pour créer dans ce sous répertoire le fichier qui devra être accessible en écriture, par exemple :
$fich = fopen("donnees/data.txt", "w"); if ($fich !== FALSE) { echo "Fichier cree avec succes"; fclose($fich); } else { echo "une erreur s'est produite"; } - vérifier l'existence de ce fichier (vous pourrez constater qu'il contient 0 octet et qu'il appartient à l'usager www-data);
-
rétablissez les droits d'accès du sous-répertoire contenant le fichier (code
755).
Et voilà! Vous avez maintenant un fichier (donnees/data.txt) dans lequel vos scripts pourront écrire!
Fermeture d'un fichier
Il est nécessaire de fermer un fichier pour s'assurer que les données écrites y soient réellement enregistrées et qu'un autre usager puisse accéder au fichier en écriture.
On utilise la fonction fclose()
Exemple :
fclose($fich);
Cette fonction retourne TRUE en cas de réussite et FALSE en cas d'échec.
Les cas d'échec sont tellement rares que la valeur de retour est rarement testée.
Écriture
Attention! Tous nos exemples utiliseront des chaînes de caractères (usage le plus fréquent des fichiers plats (flat files) en PHP! Pour écrire et lire des données binaires, voir les fonctions pack() et unpack().
Pour écrire, on peut utiliser indistinctement fwrite() et fputs(), un alias de fwrite().
Syntaxe :
int fwrite(resource descripteur, string chaîne [, int longueur]);
Le paramètre longueur est optionnel et spécifie le nombre maximal d'octets à écrire.
L'écriture s'arrête lorsque toute la chaîne est écrite ou que le nombre d'octets spécifié est atteint.
La fonction fwrite() retourne le nombre d'octets écrits ou FALSE en cas d'erreur.
Exemple :
$nb = fwrite($fich, $chaine);
if ($nb === FALSE) {
echo "Erreur d'écriture";
exit(1);
} else {
echo "$nb octets écrits";
}
Dans l'exemple précédent, il est important d'utiliser l'opérateur === et non ==, puisque le fait d'avoir écrit 0 octets n'est pas nécessairement une erreur.
Lecture
Il existe plusieurs façons de lire le contenu d'un fichier. Nous verrons tour à tour :
- la lecture ligne par ligne;
- la lecture avec élimination des balises HTML
- la lecture de fichiers CSV
- la lecture de l'intégralité d'un fichier
- la lecture caractère par caractère
- la lecture d'une longueur arbitraire.
Détection de la fin du fichier
Mais avant de voir comment lire dans un fichier, il faut savoir comment on en détecte la fin lors de la lecture.
On utilise pour cela la fonction feof() dont la syntaxe est :
bool feof(resource descripteur);
Cette fonction retourne TRUE si le "pointeur" de lecture est positionné à la fin du fichier et FALSE autrement.
Exemple :
while (! feof($fich_clients)) {
// lecture et traitement d'un enregistrement
// ...
}
Lecture ligne par ligne
On utilise la fonction fgets(), dont la syntaxe est :
string fgets(resource descripteur [, int longueur]);
La fonction fgets() s'arrête lorsqu'elle rencontre une des conditions suivantes :
- après avoir lu longueur – 1 octets;
- après avoir rencontré une fin de ligne;
- à la fin du fichier.
En cas d'absence du paramètre "longueur", la lecture se poursuit jusqu'à la fin de la ligne.
Exemple :
$fich = fopen("proverbes.txt", "r");
while (! feof($fich)) {
$ligne = fgets($fich, 256); // lit au maximum 255 caractères par ligne
echo $ligne . "<br>";
}
Lecture avec élimination des balises HTML
On voudra parfois lire le contenu d'un fichier HTML en éliminant les balises pour obtenir seulement le texte "pur".
Vous verrez encore sur le Web des exemples qui utilisent pour cela la fonction fgetss(), mais sachez que celle-ci est maintenant considérée obsolète et ne devrait plus être utilisée.
Pour lire un fichier en éliminant les balises HTML on utilise fgets() et la fonction strip_tags().
La syntaxeet de la fonction strip_tags() est :
string strip_tags(string chaîne, [string balises_autorisées]);
Le paramètre optionnel permet de spécifier les balises acceptées.
Soit un fichier HTML (incomplet) :
<h2>Un titre de niveau 2</h2> <p>Un paragraphe</p> Une ligne de texte
Le code suivant lit ligne par ligne le contenu du fichier précédent en supprimant toutes les balises HTML et PHP, à l'exception de la balise <h2> :
$fich = fopen("texte.html", "r");
while (! feof($fich)) {
$ligne = strip_tags(fgets($fich, 256), "<h2>");
echo $ligne . "<br>";
}
Sortie :
Un titre de niveau 2
Un paragrapheUne ligne de texte
Seule la balise <h2> a été conservée.
La fonction strip_tags() est souvent utilisée pour filtrer les données entrées par formulaire.
Lecture de l'intégralité d'un fichier
Pour lire un fichier au complet en une seule opération, la façon la plus intuitive consiste à...
- ouvrir le fichier;
- lire ligne par ligne son contenu;
- fermer le fichier.
Il existe heureusement des fonctions plus performantes!
readfile()
Syntaxe :
int readfile(string nom_de_fichier [, bool utiliser_include_path]);
La fonction readfile()...
- ouvre le fichier;
- imprime son contenu intégral sur la sortie standard (vers le navigateur Web);
- ferme le fichier;
- retourne le nombre total d'octets lus.
Le paramètre optionnel spécifie si l'interpréteur PHP doit rechercher le fichier dans le "include_path".
fpassthru()
Syntaxe :
int fpassthru(resource descripteur);
Fonctionne de manière semblable à readfile(), sauf que le fichier doit être préalablement ouvert.
La fonction fpassthru()...
- lit à partir de la position courante du pointeur;
- imprime son contenu intégral sur la sortie standard (vers le navigateur Web);
- ferme le fichier;
- retourne le nombre d'octets lus.
file()
Syntaxe :
array file(string nom_fichier [, utiliser_include_path]);
Ici le contenu du fichier n'est plus envoyé vers la sortie standard, mais récupéré dans un tableau.
Chaque élément du tableau contiendra une ligne du fichier.
La fonction retourne FALSE en cas de problème (ex : fichier introuvable).
file_get_contents()
Syntaxe :
string file_get_contents(string nom_fichier [, utiliser_include_path]);
Fonctionne de la même façon que file(), sauf que l'ensemble du fichier est retourné dans une seule chaîne.
En résumé
Les quatre fonctions suivantes permettent de lire un fichier au complet :
| Fonction | |
|---|---|
| readfile() | Ouvre le fichier, lit et affiche son contenu, puis le ferme. |
| fpassthru() | Lit un fichier ouvert à partir de la position courante, affiche son contenu, puis le ferme. |
| file() | Retourne le contenu du fichier dans un tableau. |
| file_get_contents() | Retourne le contenu du fichier dans une chaîne. |
Lecture caractère par caractère
Il arrive, même si cela est plutôt rare, que l'on doive lire un fichier caractère par caractère.
Syntaxe :
string fgetc(resource descripteur);
Retourne (sous forme de chaîne) le caractère à la position courante dans le fichier.
Retourne FALSE à la fin du fichier.
Exemple :
// affiche le contenu du fichier en lisant un caractère à la fois $fini = FALSE; while (!fini) { $car = fgetc($fich); if ($car !== FALSE) { echo $car; else $fini = FALSE; } // en plus condensé while (FALSE !== ($car = fgetc( $fich))) { echo $car; }
Lecture d'une longueur arbitraire
La fonction fread() lit le nombre d'octets spécifié (ou moins si la fin du fichier est rencontrée) et les retourne sous forme de chaîne.
Syntaxe :
string fread(resource descripteur, int longueur);
Exemples :
// lecture de 50 octets
$nom_fichier = "/usr/local/quelque_chose.txt";
$fich = fopen($nom_fichier, "r");
$contenu = fread($fich, 50);
fclose($fich);
// lecture de l'intégralité du fichier, soit la même chose que file_get_contents()
$nom_fichier = "/usr/local/quelque_chose.txt";
$fich = fopen($nom_fichier, "r");
$contenu = fread($fich, filesize($nom_fichier));
fclose($fich);
Détermination de la taille d'un fichier
On utilise la fonction filesize().
Syntaxe :
int filesize(string nom_fichier);
Retourne la taille en octets.
Vérification de l'existence d'un fichier
On utilise la fonction file_exists().
Syntaxe :
bool file_exists(string nom_fichier);
Permet de vérifier si un fichier existe, sans même l'ouvrir.
$nom_fichier = "/chemin/jusqu/a/fichier.txt";
echo "Le fichier $nom_fichier ";
if (file_exists($nom_fichier)) {
echo "existe";
} else {
echo "n'existe pas";
}
Suppression d'un fichier
On utilise la fonction unlink().
Syntaxe :
bool unlink(string nom_fichier);
Supprime le fichier dont le nom est passé en paramètre.
En cas d'échec (ex : droits d'accès insuffisants), retourne FALSE.
Remarque : le nom de la commande vient du monde Linux où un fichier existe tant qu'il y a un lien (link) dessus.
Les fichiers CSV
Le format CSV
Lorsqu'on utilise des fichiers plats (flat files) pour stocker des données, on doit s'assurer que ces dernières seront facilement...
- récupérables par les autres scripts;
- lisibles par les humains à des fins de débogage.
La stratégie la plus courante consiste à stocker exactement un enregistrement par ligne, le caractère de nouvelle ligne ("\n") jouant alors le rôle de séparateur d'enregistrements.
Dans chaque enregistrement (chaque ligne), les champs sont délimités par un caractère particulier, par exemple la virgule, qui joue ainsi le rôle de séparateur de champs.
Ce qui est décrit ici correspond exactement au format CSV.
Le format CSV pour "Comma Separated Value" est presque devenu un standard.
Il est utilisé entre autres par le système d'exploitation Linux (ex : le fichier /etc/passwd) et par des logiciels comme Microsoft Excel et LibreOffice Calc.
La principale caractéristique de CSV est que les enregistrements sont séparés par une fin de ligne et que les champs sont délimités (par défaut) par des virgules (comma en anglais).
Exemple de fichier CSV :
Patoche,Alain,patoche@gmail.com,Ste-Thérèse Gratton,Robert,elvis@hotmail.com,Pointe-Calumet Monette,Linda,doudoune@hotmail.com,Laval Narrache,Jean,jean.narrache@dentistes.ca,Deux-Montagnes Labrosse,Adam,adam.labrosse@dentistes.ca,Ste-Thérèse
Un fichier CSV peut tout aussi bien être lu par un logiciel comme Microsoft Excel que par un simple éditeur de texte.
Il est important de choisir des séparateurs (pour les champs et les enregistrements) qui ne se retrouveront pas dans les données.
Il sera parfois nécessaire de filtrer les données à écrire (par exemple, celles provenant d'un formulaire) pour éviter que de tels caractères ne soient introduits, malicieusement ou non, parmi les données
Écrire dans un fichier CSV
Il est facile d'écrire dans un fichier CSV sans avoir recours à une fonction spécialisée.
Exemple de création d'un fichier CSV :
define("DELIMITEUR", ":");
$fich = fopen("fichiers/clients.csv", "w");
while (...) {
...
$client = $nom . DELIMITEUR . $prenom . DELIMITEUR . $adresse . DELIMITEUR
. $telephone . "\n";
fwrite($fich, $client);
}
...
Écrire dans un fichier CSV est encore plus facile si l'information est dans un tableau. On a alors recours à la fonction implode().
Exemple :
$info = ["Patoche", "Alain", "patoche@gmail.com", "Ste-Thérèse"]; // la fonction implode() forme une chaîne de caractères à partir des éléments d'un tableau $chaine = implode(DELIMITEUR, $info); // ne pas oublier le caractère de fin de ligne $n = fwrite($fich, $chaine . "\n"); echo "$n caractères écrits";
Mais la façon la plus puissante d'écrire dans un fichier CSV demeure la fonction fputcsv().
Sa syntaxe est la suivante :
fputcsv(
resource $descripteur, // obtenu pas fopen()
array $champs, // tableau contenant les chaînes à écrire
string $separateur=",", // sépare les champs de l'enregistrement
string $encadrement = "\"", // utilisé si la chaîne contien des espaces
$echappement="\\", // pour écrire des caractères spéciaux
$fin_de_ligne="\n" // sépare les enregistrements
): int|false // retourne le nombre d'octets écrits (FALSE en cas d'erreur)
Exemple :
// remarquez l'espace dans le deuxième élément
$info = ["Frodon", "Sam Gamegie", "Merry", "Pippin"];
$nb_octets = fputcsv($fich, $info, ":");
La ligne écrite dans le fichier sera :
Frodon:"Sam Gamegie":Merry:Pippin
Lire dans un fichier CSV
Pour lire le contenu d'un fichier CSV on utilise la fonction fgetcsv() :
Sa syntaxe est la suivante :
fgetcsv(
resource $descripteur,
int $longueur = null, // longueur maximale de la ligne
string $separateur=",",
string $encadrement = "\"",
$echappement="\\"
): array|false // retourne un tableau de chaînes (FALSE en cas d'erreur)
La longueur spécifiée doit être plus grande que la plus grande ligne du fichier.
Exemple d'affichage du contenu d'un fichier CSV :
define("DELIMITEUR", ":");
define("MAX_CAR", 128);
$fich = fopen("fichiers/clients.csv", "r");
while (!feof($fich)) {
// lit une ligne
$tab_client = fgetcsv($fich, MAX_CAR, DELIMITEUR);
// affiche les données
echo "Nom : " . $tab_client[0] . "<br>";
echo "Prénom : " . $tab_client[1] . "<br>";
echo "Adresse : " . $tab_client[2] . "<br>";
echo "Téléphone : " . $tab_client[3] . "<br>";
echo "<hr>";
}
fclose($fich);
Exercices
Exercice 4-1
Vous trouverez à l'URL https://codeacademie.com/kb9/anneaux.html un fichier contenant un extrait important du roman La Communauté de l'anneau.
N'attachez pas d'importance au fait que certains caractères ne s'affichent pas correctement, puisqu'il s'agit d'un fichier HTML incomplet, sans balise pour spécifier le jeu de caractères.
Écrivez un script qui affiche ce texte en supprimant toutes les balises HTML s'y trouvant, à l'exception de la balise <strong>.
La sortie devrait ressembler à ceci :
Pour réaliser cet exercice, vous devrez d'abord récupérer le contenu du fichier distant avec file_get_contents(), puis l'afficher en supprimant certaines balises HTML avec strip_tags().
Assurez vous que la page affichée par votre script est bien valide.
Faites aussi en sorte que votre script affiche un message d'erreur si le fichier anneaux.html est introuvable. Introduisez une erreur dans le nom de fichier pour faire le test.
Exercice 4-2
Dans cet exercice, vous allez réaliser une petite application (page HTML + script PHP) permettant de constituer une mini-base de données.
Commencez par écrire le fichier bd.html (ou encore bd.php) qui présente à l'internaute un formulaire permettant d'entrer un nom, un prénom et une adresse courriel, comme dans l'exemple suivant :
Ne faites pas de validation côté client avec HTML et JavaScript et n'obligez pas l'internaute à remplir tous les champs avant la soumission du formulaire (attribut required). Il doit être possible d'envoyer un formulaire avec des champs vides pour vérifier que le script PHP côté serveur fait bien son travail de validation. C'est PHP qui dot détecter et signaler des champs non remplis.
Écrivez ensuite le script bd.php dont le rôle est de recevoir les données du formulaire et de les ajouter à chaque fois à la fin d'un fichier CSV.
Remarque : vous pouvez donner à votre fichier le suffixe .txt si le .csv vous cause des problèmes d'affichage dans le navigateur.
ATTENTION
- Vous devez vérifier si les trois champs contiennent bien des données (ici une chaîne vide n'est pas considérée comme une donnée). En cas de donnée(s) manquante(s), un message d'erreur doit être affiché et l'usager invité à compléter le formulaire.
- Il doit être possible pour l'utilisateur de visualiser FACILEMENT les modifications apportées à la base de données (fichier CSV). Après insertion. vous devez rediriger l'utilisateur vers le fichier CSV ou encore afficher son contenu automatiquement.
-
Je vous rappelle que pour qu'un script côté serveur puisse écrire dans un fichier, ce dernier doit appartenir à l'usager virtuel
www-data. Le mardi 15 septembre nous avons vu et fait en classe un exercice de création d'un fichier appartenant à l'usager www-data. Veuillez relire les notes de cours si vous étiez absent de corps ou d'esprit. -
Vous pouvez voir un exemple d'exécution de ce programme. Ici le choix a été fait d'afficher automatiquement le contenu du fichier CSV après l'insertion à partir de
bd.php. Il y a d'autres approches possibles.
Exercice 4-3
Écrivez un script PHP qui affiche dans un tableau HTML le contenu du fichier CSV de l'exercice précédent.
Exemple de sortie :
Questions et exercices de révision
Essayez de répondre à ces questions par vous-mêmes, soit en cherchant dans ce document, soit en écrivant du code. Il n'y a AUCUN BÉNÉFICE à chercher des réponses toutes faites aiileurs.
Question 1
Donnez la différence entre r+ et w+ comme deuxième paramètre de la fonction fopen().
Question 2
Que contient, pour l'usager "patoche", la variable $_SERVER['CONTEXT_DOCUMENT_ROOT']?
Question 3
Vrai ou faux? Un script PHP peut ouvrir un fichier situé sur un autre serveur.
Question 4
À quoi sert le symbole @ placé devant une instruction en PHP?
Question 5
Que va écrire le code suivant dans le fichier?
fwrite($fich, "A", 5);
Question 6
Expliquez la différence entre les opérateurs == et ===.
Question 7
Supposez que le fichier dont le descripteur est $fich contient la chaîne "ABCDEFGH". Donnez la sortie du code suivant :
$ligne = fgets($fich, 8); echo $ligne;
Question 8
Donnez le code HTML généré par la série d'instructions suivante :
$html = "<div>Un texte <strong>important</strong> à lire.</div>"; $balises = "<div>"; $sortie = strip_tags($html, $balises); echo $sortie;
Question 9
Que veut dire l'acronyme CSV? Traduisez-le en français.
Question 10
Donnez la différence entre les fonctions readfile() et fpassthru().
Question 11
Donnez la différence entre les fonctions file() et file_get_contents().
Question 12
Donnez la différence entre les fonctions fgets() et fread().