Module Stream de Node.js

Java FileModules intégrés de Node.js


Stream est une interface abstraite dans Node.js pour gérer les données en flux. Vous pouvez considérer un stream comme un flux d'eau, où les données circulent d'un endroit à un autre comme l'eau. Cette approche de traitement est particulièrement adaptée aux fichiers volumineux ou aux sources de données continues, car elle ne nécessite pas de charger toutes les données en mémoire en une seule fois.

Pourquoi avons-nous besoin des flux ?

  1. Efficacité mémoire: Lors du traitement de gros fichiers, il n'est pas nécessaire de charger l'intégralité du fichier en mémoire en une seule fois
  2. Efficacité temporelle: Les données peuvent être traitées au fur et à mesure de leur réception, sans attendre que toutes les données soient prêtes
  3. Composabilité: Plusieurs flux peuvent être connectés comme des tuyaux pour former un pipeline de traitement de données

Quatre types de flux de base

1. Flux lisible

Un flux lisible est la source des données, à partir de laquelle les données peuvent être lues. Par exemple, lire le contenu d'un fichier ou obtenir des données à partir d'une requête HTTP.

Exemple

const fs = require('fs');
const readableStream = fs.createReadStream('example.txt');

readableStream.on('data', (chunk) => {
  console.log(`Received ${chunk.length}bytes of data`);
});

readableStream.on('end', () => {
  console.log('No more data');
});

2. Flux inscriptible

Un flux inscriptible est la destination des données, dans laquelle des données peuvent être écrites. Par exemple, écrire dans un fichier ou envoyer une réponse HTTP.

Exemple

const fs = require('fs');
const writableStream = fs.createWriteStream('output.txt');

writableStream.write('First line of data\n');
writableStream.write('Second line of data\n');
writableStream.end('Last line of data');

3. Flux duplex

Un flux duplex est à la fois lisible et inscriptible, comme une socket TCP.

Exemple

const { Duplex } = require('stream');

const myDuplex = new Duplex({
  write(chunk, encoding, callback) {
    console.log(chunk.toString());
    callback();
  },
 
  read(size) {
    this.push('Données lues depuis le flux duplex');
    this.push(null); // Indique la fin des données
  }
});

4. Flux de transformation

Un flux de transformation est un type spécial de flux duplex qui peut modifier ou transformer des données pendant le processus de lecture et d'écriture. Par exemple, compresser ou chiffrer des données.

Exemple

const { Transform } = require('stream');

const upperCaseTr = new Transform({
  transform(chunk, encoding, callback) {
    this.push(chunk.toString().toUpperCase());
    callback();
  }
});

process.stdin.pipe(upperCaseTr).pipe(process.stdout);

Méthodes courantes des flux

Méthode pipe()

pipe()La méthode est l'une des fonctionnalités les plus puissantes de Stream ; elle peut connecter plusieurs flux entre eux pour former un pipeline.

Exemple

const fs = require('fs');

// Créer un flux lisible et un flux inscriptible
const readStream = fs.createReadStream('input.txt');
const writeStream = fs.createWriteStream('output.txt');

// Utiliser pipe pour connecter le flux lisible et le flux inscriptible
readStream.pipe(writeStream);

writeStream.on('finish', () => {
  console.log('Écriture des données terminée');
});

Écoute d'événements

Stream est une instance d'EventEmitter. Diverses situations peuvent être gérées en écoutant les événements :

  • data- Déclenché lorsque des données sont disponibles en lecture
  • end- Déclenché lorsqu'il n'y a plus de données à lire
  • error- Déclenché lorsqu'une erreur se produit
  • finish- Déclenché lorsque toutes les données ont été vidées vers le système sous-jacent

Exemples d'applications pratiques

Exemple 1 : Copie de fichier

Exemple

const fs = require('fs');

function copyFile(source, target, cb) {
  // Créer des flux de lecture et d'écriture
  const rd = fs.createReadStream(source);
  const wr = fs.createWriteStream(target);

  // Gérer les erreurs
  rd.on('error', err => cb(err));
  wr.on('error', err => cb(err));
 
  // Rappel d'achèvement
  wr.on('finish', cb);
 
  // Démarrer la copie
  rd.pipe(wr);
}

// Utilisation
copyFile('source.txt', 'target.txt', err => {
  if (err) console.error(err);
  else console.log('Copie terminée');
});

Exemple 2 : Serveur HTTP compressant des fichiers

Exemple

const fs = require('fs');
const http = require('http');
const zlib = require('zlib');

http.createServer((req, res) => {
  // Créer un flux lisible
  const readStream = fs.createReadStream('./largeFile.txt');
 
  // Définir les en-têtes de réponse
  res.writeHead(200, {
    'Content-Type': 'text/plain',
    'Content-Encoding': 'gzip'
  });
 
  // Chaîne de pipeline : lire -> compresser -> répondre
  readStream.pipe(zlib.createGzip()).pipe(res);
}).listen(3000);

Bonnes pratiques des flux

  1. Gestion des erreurs: ajoutez toujours des écouteurs de gestion des erreurs aux flux
  2. Gestion de la mémoire: pour les fichiers volumineux, utilisez des flux au lieu de tout lire en une seule fois
  3. Chaîne de pipeline: utilisez la méthode pipe() de manière appropriée pour combiner plusieurs flux
  4. Gestion de la contre-pression: lorsque la vitesse d'écriture ne peut pas suivre la vitesse de lecture, la contre-pression doit être gérée de manière appropriée

Exemple de gestion des erreurs

Exemple

const fs = require('fs');

const readStream = fs.createReadStream('not-exist-file.txt');

readStream.on('error', (err) => {
  console.error('Error occurred:', err.message);
});

En maîtrisant le module Stream de Node.js, vous pouvez gérer efficacement diverses opérations d'E/S. Surtout lors du traitement de fichiers volumineux ou de données en temps réel, les flux deviendront votre outil puissant.

Java FileModules intégrés de Node.js

Autres extensions