Développement d'applications Web avec LAMP

Document d'accompagnement pour le cours 420-KB9-LG

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 "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 :

  1. un fichier inexistant;
  2. 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 :

Warning: fopen(fichiers/blabla.txt): failed to open stream: No such file or directory in /var/www/html/test_fichiers.php on line 37

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 :

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 :

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 :

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 paragraphe
Une 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 à...

Il existe heureusement des fonctions plus performantes!

readfile()

Syntaxe :

int readfile(string nom_de_fichier [, bool utiliser_include_path]);

La fonction readfile()...

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()...

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...

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 :

Les anneaux de pouvoir Trois anneaux pour les Rois Elfes sous le ciel, Sept pour les Seigneurs Nains dans leurs demeures de pierre, Neuf pour les Hommes Mortels destinés au trépas, Un pour le Seigneur Ténébreux sur son sombre trône, Dans le Pays de Mordor où s'étendent les Ombres. Un anneau pour les gouverner tous. Un anneau pour les trouver, Un anneau pour les amener tous et dans les ténèbres les lier Au Pays de Mordor où s'étendent les Ombres. — J. R. R. Tolkien, La Communauté de l'anneau

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.

Solution


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 :

formulaire

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


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 :

tableau


Questions et exercices de révision

AVERTISSEMENT

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().