1. Introduction au module fs (File System)
Le module fs
(File System) est intégré à Node.js et permet de lire, écrire, et manipuler des fichiers sur le disque. Contrairement au JavaScript dans le navigateur, où l’accès au système de fichiers est inexistant, Node.js vous donne un contrôle total.
Exemple de base : Lire un fichier
Commençons par lire un fichier texte avec la méthode fs.readFile
:
1const fs = require('fs');
2
3fs.readFile('exemple.txt', 'utf8', (err, data) => {
4 if (err) {
5 console.error('Erreur :', err);
6 return;
7 }
8 console.log('Contenu du fichier :', data);
9});
Écrire dans un fichier
Pour écrire dans un fichier, utilisons fs.writeFile
:
1fs.writeFile('nouveau.txt', 'Bonjour Node.js !', (err) => {
2 if (err) {
3 console.error('Erreur :', err);
4 return;
5 }
6 console.log('Fichier écrit avec succès !');
7});
2. Gérer l’asynchronisme : Callbacks, Promises, et Async/Await
Les callbacks
Les callbacks sont la méthode historique de Node.js pour gérer l’asynchronisme. Cependant, ils peuvent conduire à un "callback hell" si les opérations s’enchaînent. Exemple :
1fs.readFile('fichier1.txt', 'utf8', (err, data1) => {
2 if (err) return console.error(err);
3 fs.readFile('fichier2.txt', 'utf8', (err, data2) => {
4 if (err) return console.error(err);
5 console.log(data1, data2);
6 });
7});
Promises avec fs.promises
Depuis Node.js 10, le module fs.promises
offre une alternative basée sur les Promises, plus lisible :
1const fs = require('fs').promises;
2
3fs.readFile('exemple.txt', 'utf8')
4 .then(data => console.log('Contenu :', data))
5 .catch(err => console.error('Erreur :', err));
Async/Await
Pour encore plus de clarté, utilisons async/await
(familier aux étudiants venant du navigateur) :
1const fs = require('fs').promises;
2
3async function lireFichier() {
4 try {
5 const data = await fs.readFile('exemple.txt', 'utf8');
6 console.log('Contenu :', data);
7 } catch (err) {
8 console.error('Erreur :', err);
9 }
10}
11
12lireFichier();
3. Introduction aux Streams : Gérer les gros fichiers
Pourquoi les streams ?
Imaginez un fichier de 1 Go. Le charger entièrement en mémoire avec fs.readFile
risque de saturer votre programme. Les streams permettent de traiter les données par petits morceaux (chunks), comme un flux continu.
Types de streams dans Node.js
- Readable : Pour lire des données (ex. lire un fichier).
- Writable : Pour écrire des données (ex. écrire dans un fichier).
- Duplex : Lecture et écriture combinées.
- Transform : Pour modifier les données en transit.
Exemple : Lire un fichier avec un Readable Stream
Utilisons fs.createReadStream
:
1const fs = require('fs');
2
3const readStream = fs.createReadStream('grosfichier.txt', { encoding: 'utf8' });
4
5readStream.on('data', (chunk) => {
6 console.log('Nouveau morceau :', chunk);
7});
8
9readStream.on('end', () => {
10 console.log('Lecture terminée !');
11});
12
13readStream.on('error', (err) => {
14 console.error('Erreur :', err);
15});
data
: Événement déclenché pour chaque morceau de données.end
: Fin de la lecture.error
: Gestion des erreurs.
Écrire avec un Writable Stream
Pour écrire dans un fichier :
1const writeStream = fs.createWriteStream('sortie.txt');
2
3writeStream.write('Premier morceau\n');
4writeStream.write('Deuxième morceau\n');
5writeStream.end(); // Termine l’écriture
6
7writeStream.on('finish', () => {
8 console.log('Écriture terminée !');
9});
Piping : Connecter les streams
Le pipe permet de connecter un Readable Stream à un Writable Stream, simplifiant les opérations comme copier un fichier :
1const readStream = fs.createReadStream('source.txt');
2const writeStream = fs.createWriteStream('destination.txt');
3
4readStream.pipe(writeStream);
5
6writeStream.on('finish', () => {
7 console.log('Copie terminée !');
8});
4. Cas pratique : Compter les lignes d’un fichier volumineux
Mettons tout ensemble avec un exemple utile :
1const fs = require('fs');
2
3const readStream = fs.createReadStream('grosfichier.txt', { encoding: 'utf8' });
4let lineCount = 0;
5
6readStream.on('data', (chunk) => {
7 lineCount += (chunk.match(/\n/g) || []).length;
8});
9
10readStream.on('end', () => {
11 console.log(`Nombre de lignes : ${lineCount}`);
12});
13
14readStream.on('error', (err) => {
15 console.error('Erreur :', err);
16});
5. Bonnes pratiques
- Gestion des erreurs : Toujours écouter l’événement
error
sur les streams. - Encodage : Spécifiez utf8 pour travailler avec du texte lisible.
- Performance : Préférez les streams pour les gros fichiers ou les données en continu (ex. vidéos, logs).
Conclusion
Vous savez maintenant manipuler des fichiers avec Node.js, de la lecture/écriture simple aux streams pour les gros volumes de données. Ces compétences sont essentielles pour des applications comme des serveurs web, des outils CLI, ou des scripts d’automatisation. Dans un prochaine article, nous verrons comment utiliser les streams dans un serveur HTTP !