Français

Outils de développement · Encodeur et décodeur Base64

Décodage de Base64 en UTF-8 sans mojibake : atob plus TextDecoder

· Comment ça marche

base64 codage unicode

Pipeline de Base64 à UTF-8 montrant des échecs de Mojibake
Illustration vectorielle originale de ToolAcre

atob() renvoie des octets déguisés en caractères, c'est pourquoi le texte accentué semble brisé après le décodage. Cet article montre le pipeline correct de Base64 aux octets vers le texte UTF-8, et comment reconnaître le modèle d'échec.

La réponse de l'API qui décode en "Café" - un symptôme concret de mojibake et les deux octets derrière les deux mauvais caractères

Une chaîne Base64 Q2Fmw6k= décode en octets (67, 97, 102, 195, 169), qui sont UTF-8 texte Café. Collez dans un décodeur naïf (juste une conversion d'atob et de chaîne) et la sortie est souvent Café, chaque accent remplacé par deux mauvais caractères. Ce mojibake se produit parce qu'atob renvoie une chaîne d'octets (unités de code 0–255), et non du texte UTF-8. Les octets 195 et 169 codent le é accentué en UTF-8.

Les traiter comme si des caractères latins-1 séparés donnaient un motif mojibake. Le pipeline correct est atob (octets sous forme de chaîne), puis TextDecoder (interpréter les octets comme UTF-8) et le texte original revient. La fonction atob n'est pas interrompue ; il est conçu pour les données binaires. Son nom vient de l'ASCII vers binaire et la chaîne binaire qu'il produit est une séquence d'unités de code 0–255, chacune représentant un octet.

Ce qu'atob() renvoie réellement : une chaîne d'unités de code 0–255 qui représentent des octets, pas du texte décodé

Si vous lui fournissez Q2Fmw6k= (standard Base64), il génère une chaîne où chaque caractère est d'un octet : unité de code 67, puis 97, puis 102, puis 195, puis 169. Si vous affichez cette chaîne directement ou si vous l'interprétez comme du texte Latin-1, vous voyez une sortie tronquée. L'étape manquante consiste à convertir les unités de code en tableau d'octets, puis à décoder le tableau en tant que UTF-8.

La boucle charCodeAt récupère les valeurs d'octets : pour chaque caractère de la sortie atob, appelez charCodeAt pour obtenir l'unité de code (numéro 0–255), stockée dans Uint8Array. Une fois le tableau d'octets existant, transmettez-le à TextDecoder avec le jeu de caractères utf-8. TextDecoder lit la séquence d'octets et l'interprète comme du texte UTF-8, combinant des séquences d'octets comme (195, 169) en caractères uniques comme é. Les octets (67, 97, 102, 195, 169) deviennent une chaîne de quatre caractères Café. La boucle est délibérément ennuyeuse : lisez chaque unité de code renvoyée avec charCodeAt et affectez-la à la position Uint8Array correspondante. Aucune décision de caractère ne s’y produit. La seule interprétation arrive lorsque TextDecoder reçoit ce tableau et applique UTF-8 avec une gestion des erreurs fatales.

Transformer cette chaîne en Uint8Array - la boucle charCodeAt et pourquoi il s'agit d'une copie d'octets, pas d'une conversion

Ce processus en deux étapes (récupération d'octets, puis interprétation UTF-8) est ce que fait l'encodeur et le décodeur Base64 en interne. Le motif mojibake est un signe révélateur de cette erreur. Si Café apparaît comme Café, vous voyez une interprétation Latin-1 de UTF-8 octets. UTF-8 octets pour é sont 0xC3 0xA9 (décimal 195, 169). En latin-1, l'unité de code 195 est à et l'unité de code 169 est ©.

Lorsque la séquence d'octets UTF-8 est lue comme si chaque octet était un caractère Latin-1 distinct, chaque séquence UTF-8 multi-octets produit des caractères de remplacement incorrects. Si Café apparaît comme Caf suivi d'un personnage de remplacement, ou comme Caf ? ou Caf plus U+FFFD, vous voyez un échec différent : le décodeur n'a pas reconnu la séquence d'octets comme UTF-8 valide. Un exemple concret : Base64 SGVsbG8sIOS4lueVjCEg8J-Zgg== décode comme suit.

TextDecoder et la décision du jeu de caractères - décodage en tant que UTF-8, et pourquoi le jeu de caractères est un fait distinct que vous devez savoir

atob produit une chaîne binaire avec des octets (72, 101, 108, 108, 111, 44, 32, 228, 184, 180, 149, 140, 33, 32, 240, 159, 152, 130). Les six premiers octets sont ASCII : devenez Bonjour. Les octets 228, 184, 180 sont une séquence UTF-8 de trois octets représentant le caractère CJK. Les octets 149, 140 font partie de la séquence suivante. La séquence complète comprend une séquence emoji de quatre octets (240, 159, 152, 130) pour le caractère final.

Lorsqu'ils sont traités correctement via TextDecoder, tous les octets se combinent pour produire un texte original en script mixte. Les séquences d'octets UTF-8 ont des longueurs prévisibles : l'octet commençant par 0xxxxxxx est un ASCII à un octet ; l'octet commençant par 110xxxxx attend l'octet suivant commençant par 10xxxxxx (deux octets au total) ; l'octet commençant par 1110xxxx attend deux octets suivants (trois octets au total) ; l'octet commençant par 11110xxx attend trois octets suivants (quatre octets au total). Pour un échantillon mixte CJK et emoji, la vue des octets est particulièrement diagnostique car l'intuition ASCII n'aide plus. Plusieurs octets appartiennent à chaque symbole visible, et une suppression d'un octet décale la séquence restante en UTF-8 non valide. Un décodage strict transforme ce changement en un échec nommé au lieu de dommages apparemment plausibles.

Exemple concret : décodage d'une chaîne Base64 contenant du CJK et un emoji - octets, points de code et chaîne finale par rapport à l'original

La séquence commençant par 1111110x n'est pas valide dans UTF-8 (réservée pour le futur, non utilisée). L'octet commençant par 10xxxxxx ne doit jamais apparaître comme octet de tête ; c'est la continuation. Si le flux d'octets enfreint les règles, il n'est pas valide UTF-8. TextDecoder avec charset utf-8 interprète le tableau selon ces règles et réussit pour les séquences valides. Pour invalide, il signale une erreur.

L'encodeur et le décodeur Base64 utilisent TextDecoder avec l'indicateur de mode strict true. Cela signifie qu'un UTF-8 non valide génère une erreur plutôt que d'insérer silencieusement des caractères de remplacement (U+FFFD). Si la chaîne Base64 décode en octets qui ne sont pas valides UTF-8, le mode strict sera lancé au lieu de continuer avec un texte tronqué. Il s'agit d'un choix de conception : les charges utiles binaires (images, clés, données compressées) ne sont pas du texte et ne doivent pas être décodées en tant que texte.

Reconnaître le modèle : Ã, †et � – comment distinguer un problème Base64 d'un problème de jeu de caractères

Si vous tentez de décoder JPEG en Base64, le flux d'octets ne représentera pas un UTF-8 valide et le décodage strict le rejettera. L'outil offre une vue hexadécimale pour de telles charges utiles : vous pouvez voir les octets bruts sans prétendre qu'il s'agit de texte. Reconnaître les erreurs de décodage UTF-8 implique d'examiner les octets dans leur contexte. S'agit-il d'un nombre impair là où une séquence multi-octets est attendue ?

Le premier octet de la séquence potentielle est-il invalide (commençant par 10xxxxxx) ? Des octets de continuation sont-ils manquants ? Le bouton de sortie d’octets constitue le fork le plus propre de l’enquête. Si hex apparaît mais que le décodage du texte échoue, l'analyse Base64 a réussi et la charge utile est soit binaire, endommagée, soit codée avec un jeu de caractères différent. La modification de la ponctuation Base64 ne peut pas réparer une incompatibilité de jeu de caractères une fois que les octets corrects sont déjà apparus.

Ce que cela ne couvre pas : charges utiles UTF-16, sorties binaires telles que les images et gestion des octets invalides

Les modèles sont cohérents. Un seul octet 0xFF n'est jamais valide dans UTF-8 ; il ne peut pas s'agir d'un octet ASCII (seuls 0–127 sont ASCII) et ne peut pas être un octet de tête (les octets de tête sont 0xC0–0xFD, 0xFF est réservé). Les mères porteuses isolées (concept UTF-16) ne peuvent pas apparaître dans UTF-8 ; si vous voyez la séquence d'octets 0xED 0xA0 0x80 (qui code le substitut U+D800 dans le style UTF-8), elle n'est pas valide UTF-8.

Une solution de contournement historique est btoa(unescape(encodeURIComponent(text))). encodeURIComponent transforme café en %C3%A9 (codage en pourcentage UTF-8 octets), déséchappe les reconditionnements en unités de code, btoa encode les unités de code. Cela fonctionne pour la plupart des textes mais est fragile en présence de substituts isolés et difficile à lire. Le pipeline moderne (TextEncoder en octets, puis en base64) est plus clair et standard. TextEncoder est intégré à tous les navigateurs modernes et à Node.js, ce qui fait le bon choix. UTF-16, les anciens codages à un octet et le contenu de fichiers arbitraires nécessitent un décodeur sélectionné pour ces octets ou un visualiseur binaire. ToolAcre ne devine pas intentionnellement parmi eux. Deviner pourrait transformer une séquence invalide en texte trompeur, tandis qu'un vidage hexadécimal préserve chaque octet pour une interprétation ultérieure et éclairée.

À retenir : Base64 vous donne des octets, UTF-8 vous donne du texte - comment l'encodeur et le décodeur Base64 effectuent les deux étapes afin que le texte décodé corresponde exactement à l'entrée

Lorsque vous avez une chaîne Base64 et que vous souhaitez du texte UTF-8, les étapes complètes sont les suivantes : décoder Base64 en octets (en utilisant la bibliothèque de décodage atob ou base64), créer Uint8Array à partir d'octets, transmettre le tableau à TextDecoder avec le jeu de caractères utf-8, lire le résultat sous forme de chaîne.

Si l'entrée est constituée de données binaires plutôt que de texte, ignorez TextDecoder et examinez directement les octets. L'encodeur et le décodeur Base64 fournissent une vue hexadécimale des octets, préservant les valeurs que le décodage strict UTF-8 rejetterait. Ce fork est diagnostique : les octets réussis et le texte ayant échoué signifient que l'analyse Base64 a fonctionné, tandis que la charge utile est binaire, endommagée ou codée avec un jeu de caractères que cet outil ne devine pas.