
Encodage et décodage de données (UTF-8, ASCII, etc.)
Apprenez a convertir des chaines de caracteres en Buffers et vice-versa en utilisant differents encodages (UTF-8, ASCII, Latin1, Base64, Hex) avec Node.js.
Le pont entre les octets et les caracteres : l'encodage
Les Buffers Node.js, comme nous l'avons vu, stockent des séquences d'octets bruts. Cependant, nos applications manipulent très souvent du texte sous forme de chaînes de caractères JavaScript. Pour passer de l'un à l'autre – convertir une chaîne en une séquence d'octets pour la stocker ou la transmettre, ou interpréter une séquence d'octets reçue comme du texte – nous avons besoin d'un ensemble de règles bien définies : c'est ce qu'on appelle un encodage de caractères (character encoding).
Un encodage spécifie comment mapper chaque caractère d'un certain répertoire (comme Unicode) à une séquence spécifique d'un ou plusieurs octets, et inversement. Le choix de l'encodage est crucial car utiliser le mauvais encodage lors de la lecture ou de l'écriture entraînera une mauvaise interprétation des données, conduisant à des caractères incorrects (souvent représentés par des points d'interrogation, des losanges noirs �, ou des séquences étranges comme 'é' pour 'é') ou même à des erreurs.
Node.js, via l'API Buffer, offre un support intégré pour plusieurs encodages courants, permettant des conversions fluides entre les représentations binaires (Buffers) et textuelles (chaînes JavaScript).
Les principaux encodages supportes par Node.js
Voici les encodages les plus fréquemment utilisés avec les Buffers Node.js :
'utf8'(ou'utf-8') : L'encodage standard de facto pour le web et de nombreuses applications modernes. Il peut représenter tous les caractères Unicode en utilisant une séquence de 1 à 4 octets par caractère. Les caractères ASCII de base (0-127) sont encodés sur un seul octet, ce qui le rend partiellement compatible avec l'ASCII. C'est l'encodage par défaut pour la plupart des opérations sur chaînes dans Node.js et avec les Buffers.'ascii': Encodage 7 bits pour les caractères anglais de base. Ne peut représenter que 128 caractères. Les octets dont le bit de poids fort est à 1 (valeurs > 127) sont souvent tronqués ou remplacés (généralement par 0x3f, le code de '?'). A n'utiliser que si vous êtes certain que vos données sont purement ASCII.'latin1'(alias'binary') : Encodage 8 bits (un octet par caractère) basé sur la norme ISO-8859-1. Il peut représenter les caractères des langues d'Europe occidentale. C'est parfois utilisé à tort comme un moyen de traiter des données binaires arbitraires comme des chaînes, mais ce n'est pas recommandé car cela peut entraîner des corruptions si les données ne sont pas réellement du Latin-1 valide.'ucs2'(alias'utf16le'- Little Endian UTF-16) : Encodage 16 bits (2 octets par caractère, sauf pour les paires de substitution Unicode). C'est l'encodage utilisé en interne par JavaScript pour représenter les chaînes en mémoire. Utile dans certains contextes d'interopérabilité, mais moins courant pour les échanges de données que UTF-8.'base64': Ce n'est pas un encodage de caractères au sens strict, mais un encodage binaire-vers-texte. Il représente des données binaires arbitraires (séquences d'octets) en utilisant uniquement un sous-ensemble de caractères ASCII (A-Z, a-z, 0-9, +, / et = pour le padding). Très utilisé pour inclure des données binaires dans des formats textuels comme les e-mails (pièces jointes), les Data URLs, ou le JSON.'hex': Encode chaque octet (8 bits) sous forme de deux caractères hexadécimaux (0-9, a-f). Par exemple, l'octet `0xFF` devient la chaîne `'ff'`. Utile pour le débogage, l'affichage compact de données binaires, ou dans certains protocoles.
Convertir une chaine en Buffer (`Buffer.from`)
Pour encoder une chaîne JavaScript en une séquence d'octets dans un Buffer, on utilise `Buffer.from(string, [encoding])`. Si l'encodage n'est pas spécifié, Node.js utilise `'utf8'` par défaut.
const message = '€uro'; // Contient un caractère multi-octets en UTF-8
// Encodage UTF-8 (par défaut)
const bufUtf8 = Buffer.from(message);
console.log(`UTF-8 (${bufUtf8.length} octets):`, bufUtf8); // ('€' prend 3 octets, 'u', 'r', 'o' 1 octet chacun)
// Tentative d'encodage ASCII (perd le caractère €)
const bufAscii = Buffer.from(message, 'ascii');
console.log(`ASCII (${bufAscii.length} octets):`, bufAscii); // ('€' est remplacé par '?' = 0x3f)
// Encodage Latin1 (interprète mal les octets de €)
const bufLatin1 = Buffer.from(message, 'latin1');
console.log(`Latin1 (${bufLatin1.length} octets):`, bufLatin1); // (comportement peut varier, souvent perte)
// Encodage Hex (interprète la chaîne '€uro' comme des chiffres hexa - NE FAIT PAS CE QUE L'ON PENSE)
// Ceci n'encode PAS le texte en hexa, mais tente de décoder la chaîne '€uro' comme si c'était déjà de l'hexa.
// Pour encoder en Hex, il faut d'abord créer le buffer (ex: en UTF-8) puis le convertir en chaîne hex.
// const bufHexDecodeAttempt = Buffer.from(message, 'hex'); // Va probablement échouer ou donner n'importe quoi
// Encodage Base64 (idem, ne fait pas ce que l'on pense directement)
// const bufBase64DecodeAttempt = Buffer.from(message, 'base64'); // Idem
Il est essentiel de choisir l'encodage qui correspond à la manière dont les données textuelles doivent être représentées en octets.
Convertir un Buffer en chaine (`buf.toString`)
Pour décoder une séquence d'octets d'un Buffer en une chaîne JavaScript lisible, on utilise `buf.toString([encoding], [start], [end])`. Encore une fois, `'utf8'` est l'encodage par défaut si aucun n'est fourni.
// Supposons que nous recevons ces octets (représentation UTF-8 de '€uro')
const receivedBytes = Buffer.from([0xe2, 0x82, 0xac, 0x75, 0x72, 0x6f]);
// Décodage UTF-8 (correct)
const textUtf8 = receivedBytes.toString('utf8'); // ou simplement toString()
console.log('Décodé en UTF-8:', textUtf8); // '€uro'
// Tentative de décodage ASCII (incorrect)
const textAscii = receivedBytes.toString('ascii');
console.log('Décodé en ASCII:', textAscii); // 'â?¬uro' ou similaire (mauvaise interprétation)
// Tentative de décodage Latin1 (incorrect)
const textLatin1 = receivedBytes.toString('latin1');
console.log('Décodé en Latin1:', textLatin1); // '€uro' (mauvaise interprétation)
// --- Cas de Base64 et Hex ---
// Supposons qu'on ait un buffer (ex: les octets de 'Node')
const nodeBuf = Buffer.from('Node'); //
// Encoder ce buffer en chaîne Base64
const base64String = nodeBuf.toString('base64');
console.log('Buffer en Base64:', base64String); // 'Tm9kZQ=='
// Décoder la chaîne Base64 pour retrouver le Buffer original
const bufFromBase64 = Buffer.from(base64String, 'base64');
console.log('Base64 décodé:', bufFromBase64); //
console.log('... en texte:', bufFromBase64.toString('utf8')); // 'Node'
// Encoder le buffer en chaîne Hex
const hexString = nodeBuf.toString('hex');
console.log('Buffer en Hex:', hexString); // '4e6f6465'
// Décoder la chaîne Hex pour retrouver le Buffer original
const bufFromHex = Buffer.from(hexString, 'hex');
console.log('Hex décodé:', bufFromHex); //
console.log('... en texte:', bufFromHex.toString('utf8')); // 'Node'
La clé est d'utiliser le même encodage pour `toString()` que celui qui a été utilisé pour créer les octets dans le Buffer (ou celui attendu par le protocole/format de données).
Choisir le bon encodage : quand utiliser quoi ?
`utf8` : Le choix par défaut pour tout texte destiné à être lu par des humains ou échangé via des protocoles web standards (HTTP, JSON, etc.). Gère tous les caractères internationaux.
`ascii` : Uniquement si vous traitez des données garanties 100% ASCII (rares en dehors de certains protocoles très spécifiques ou systèmes anciens).
`latin1` : Principalement pour la compatibilité avec d'anciens systèmes ou protocoles spécifiant explicitement cet encodage. A éviter comme substitut pour manipuler des données binaires quelconques.
`base64` : La solution standard pour représenter des données binaires (images, sons, fichiers quelconques) sous forme de texte, afin de les intégrer dans des formats qui ne supportent que le texte (JSON, XML, e-mail, Data URLs).
`hex` : Utile pour l'affichage de débogage de données binaires, les checksums, ou lorsque des protocoles spécifiques nécessitent une représentation hexadécimale.
Comprendre et utiliser correctement les encodages avec les Buffers est fondamental pour assurer l'intégrité des données lors des conversions entre le monde binaire des octets et le monde textuel des caractères en Node.js.