DanLevy.net

Quiz : Maîtrise de l’E/S Node.js

Testez vos connaissances des fichiers, flux et tampons

Prêt à plonger dans l’univers du I/O NodeJS ? 🌊

Ce quiz évaluera votre maîtrise des opérations d’I/O de Node, des tâches de base du système de fichiers aux concepts avancés de streaming. Nous aborderons les buffers, les encodages et les bonnes pratiques pour manipuler les données de façon efficace.

Voyons à quel point vous distinguez vos streams de vos buffers ! 🚀

Que fait ce code ?

const buf = Buffer.alloc(5);
console.log(buf);

Buffer.alloc(size) crée un nouveau Buffer de la taille spécifiée rempli de zéros. Le résultat sera : <Buffer 00 00 00 00 00>

Si vous voulez créer un Buffer avec des données aléatoires, utilisez Buffer.allocUnsafe(5).

En savoir plus sur l’allocation de Buffer

Que va-t‑il afficher ?

const buf = Buffer.from([65]);
console.log(buf.toString());

Les nombres dans le tableau représentent des codes ASCII :

  • 65 : ‘A’

toString() convertit ces octets en leur représentation chaîne en utilisant l’encodage UTF‑8 par défaut.

En savoir plus sur l’encodage des Buffers

Quel est l’ordre de sortie ?

import fs from 'fs';
fs.readFile('test.txt', 'utf8', (err, data) => {
console.log(data);
});
console.log('Done');

Comme readFile est asynchrone, le code continue de s’exécuter pendant que le fichier est lu. Par conséquent, “Done” sera affiché avant le contenu du fichier.

Pour attendre que le fichier soit lu d’abord, vous pouvez utiliser la version basée sur les Promises :

import { promises as fs } from 'fs';
async function read() {
const data = await fs.readFile('test.txt', 'utf8');
console.log(data);
console.log('Done');
}

Que renvoie fs.readFileSync() par défaut ?

import fs from 'fs';
const content = fs.readFileSync('test.txt');

fs.readFileSync() renvoie un Buffer par défaut lorsqu’aucun encodage n’est spécifié. Si vous voulez une chaîne, vous devez soit :

  1. Spécifier un encodage : fs.readFileSync('test.txt', 'utf8')
  2. Convertir le Buffer : content.toString()

En savoir plus sur fs.readFileSync dans la documentation Node.js

Quel ensemble d’événements est couramment utilisé avec les flux Readable ?

Les flux Readable émettent plusieurs événements importants :

  • ‘data’ : lorsque des données sont disponibles à la lecture
  • ‘end’ : lorsqu’il n’y a plus de données à lire
  • ‘error’ : lorsqu’une erreur se produit
  • ‘close’ : lorsque le flux et la ressource sous-jacente sont fermés
const readable = fs.createReadStream('file.txt');
readable.on('data', chunk => console.log(chunk));
readable.on('end', () => console.log('Done!'));

En savoir plus sur les événements de flux

Que fait ce code ?

import fs from 'fs';
const readable = fs.createReadStream('source.txt');
const writable = fs.createWriteStream('dest.txt');
readable.pipe(writable);

pipe() connecte un flux lisible à un flux inscriptible, gérant automatiquement la pression arrière et copiant les données par morceaux sans charger le fichier entier en mémoire.

C’est efficace en mémoire pour les gros fichiers comparé à fs.readFile() suivi de fs.writeFile().

En savoir plus sur pipe()

Que fait l’option recursive ?

import fs from 'fs';
fs.mkdirSync('./a/b/c', { recursive: true });

L’option recursive: true crée les répertoires parents s’ils n’existent pas. Sans cette option, tenter de créer ’./a/b/c’ lancerait une erreur si ’./a’ ou ’./a/b’ n’existent pas.

C’est similaire à la commande shell mkdir -p.

En savoir plus sur mkdir

Quel sera le résultat ?

import { Transform } from 'stream';
const upperCase = new Transform({
transform(chunk, encoding, callback) {
callback(null, chunk.toString().toUpperCase());
}
});
process.stdin
.pipe(upperCase)
.pipe(process.stdout);
// Input: "hello world"

Les flux de transformation modifient les données au passage. Ici, chaque morceau est :

  1. Converti en chaîne
  2. Transformé en majuscules
  3. Envoyé vers stdout

Cela crée un pipeline qui convertit toutes les entrées en majuscules.

En savoir plus sur les flux de transformation

Combien de fois fs.watch() est‑il garanti de se déclencher lorsqu’un fichier est modifié ?

import fs from 'fs';
fs.watch('test.txt', (eventType, filename) => {
console.log(`${filename} was changed`);
});
// Then modify test.txt once

fs.watch() n’est pas garanti de se déclencher exactement une fois par modification logique du fichier. Il se déclenche souvent plusieurs fois parce que de nombreux éditeurs de texte :

  1. Enregistrent dans un fichier temporaire
  2. Le renomment en fichier cible

Pour une surveillance plus fiable, envisagez d’utiliser :

  • Le package chokidar
  • Un debounce du rappel
  • fs.watchFile() (bien que moins efficace)

En savoir plus sur fs.watch()

Quelle est la sortie ?

const buf1 = Buffer.from('Hello');
const buf2 = Buffer.from('Hello');
console.log(buf1 === buf2);

Les buffers sont comparés par référence, pas par valeur. Même s’ils contiennent les mêmes données, ce sont des objets différents.

Pour comparer le contenu des buffers, utilisez :

buf1.equals(buf2) // true
// or
Buffer.compare(buf1, buf2) === 0 // true

En savoir plus sur la comparaison de Buffer

Quel est le but principal de la rétropression des flux ?

La rétropression est un mécanisme qui empêche le débordement de mémoire en suspendant la lecture lorsque l’extrémité d’écriture ne peut pas suivre.

Exemple de rétropression manuelle :

readable.on('data', (chunk) => {
const canContinue = writable.write(chunk);
if (!canContinue) {
readable.pause();
writable.once('drain', () => readable.resume());
}
});

pipe() gère cela automatiquement!

En savoir plus sur la rétropression

Que fait ce code ?

import fs from 'fs';
fs.symlinkSync('target.txt', 'link.txt');

symlinkSync crée un lien symbolique (comme un raccourci) vers le fichier cible.

Principales différences avec les liens physiques :

  • Peut lier des répertoires
  • Peut traverser des systèmes de fichiers
  • Se rompt si la cible est supprimée

Pour créer un lien physique à la place :

fs.linkSync('target.txt', 'hardlink.txt');

En savoir plus sur les liens symboliques

Dans quels modes les flux Node.js peuvent-ils fonctionner ?

Les flux peuvent fonctionner en :

  1. Mode binaire (par défaut) : pour les tampons et les chaînes
  2. Mode objet : pour toute valeur JavaScript

Exemple de mode objet :

import { Transform } from 'stream';
const objectStream = new Transform({
objectMode: true,
transform(chunk, encoding, callback) {
callback(null, { value: chunk });
}
});

En savoir plus sur les modes de flux

Quel type est le paramètre fd dans ce rappel ?

import fs from 'fs';
fs.open('test.txt', 'r', (err, fd) => {
console.log(typeof fd);
});

Les descripteurs de fichiers sont des nombres qui identifient de façon unique les fichiers ouverts dans le système d’exploitation.

Les trois premiers descripteurs sont réservés :

  • 0 : stdin
  • 1 : stdout
  • 2 : stderr

N’oubliez jamais de fermer les descripteurs de fichiers :

fs.close(fd, (err) => {
if (err) throw err;
});

En savoir plus sur les descripteurs de fichiers

Combien d’octets cette chaîne occupera-t-elle en UTF-8 ?

const str = "Hello 🌍";
const buf = Buffer.from(str);
console.log(buf.length);

En UTF-8 :

  • Les caractères ASCII (comme ‘Hello ’) prennent 1 octet chacun
  • L’emoji terre 🌍 prend 4 octets

Donc : 5 (Hello) + 1 (espace) + 4 (🌍) = 10 octets

Pour voir les octets :

console.log(buf); // <Buffer 48 65 6c 6c 6f 20 f0 9f 8c 8d>

En savoir plus sur l’encodage UTF-8

J’espère que vous avez apprécié tester vos connaissances Node JS IO ! Vous en voulez plus ? Consultez ma [Collection de Quiz]../challenges/ pour d’autres défis !