Quando Base64 sembra "rompere il cinese", il problema è solitamente il confine tra caratteri e byte. Base64 non sa se una sequenza rappresenta testo o emoji cinese. Conserva i byte; l'applicazione sceglie il modo in cui tali byte vengono prodotti e interpretati.
Segui i byte
Il carattere 中 è U+4E2D. In UTF-8 utilizza i byte E4 B8 AD, la cui rappresentazione Base64 è 5Lit. Una codifica dei caratteri diversa produce byte diversi e quindi un valore Base64 diverso. Concordare su UTF-8 ad entrambe le estremità prima di confrontare le stringhe codificate.
const bytes = new TextEncoder().encode('中');
console.log([...bytes]); // [228, 184, 173]
console.log([...bytes].map(b => b.toString(16)).join(' ')); // e4 b8 ad
Le emoji illustrano un'altra distinzione: JavaScript '😊'.length è due unità di codice UTF-16, mentre la sua rappresentazione UTF-8 ha quattro byte. Nessuno dei due numeri da solo è un conteggio di caratteri visibili percepiti dall'utente in un testo arbitrario. Utilizza la lunghezza in byte per i calcoli di file e trasporto.
Rendi visibile la sostituzione
Il carattere sostitutivo � può significare che un decodificatore precedente ha già perso informazioni. Una volta che i byte sconosciuti sono stati sostituiti in una stringa e la stringa viene ricodificata, i valori originali generalmente non possono essere ricostruiti. Ispezionare l'array di byte decodificato grezzo prima di effettuare ulteriori conversioni.
const decoder = new TextDecoder('utf-8', { fatal: true });
console.log(decoder.decode(Uint8Array.of(0xe4, 0xb8, 0xad))); // 中
try { decoder.decode(Uint8Array.of(0xff)); }
catch { console.log('Invalid UTF-8; preserve the original byte.'); }
La normalizzazione è un'operazione separata
Due stringhe possono sembrare identiche pur contenendo sequenze Unicode diverse. La lettera accentata é può essere un carattere precomposto o una e seguita da un accento combinato. UTF-8 e Base64 preservano correttamente questa differenza. Se la tua applicazione richiede testo normalizzato, scegli esplicitamente un modulo di normalizzazione e applicalo prima della codifica; non chiamare mai un risultato modificato una riparazione con conservazione dei byte.
Controlla anche i caratteri invisibili, le terminazioni di riga e un possibile contrassegno dell'ordine dei byte quando i risultati differiscono. Questi sono byte di input reali, non necessariamente bug del codificatore. Per i messaggi firmati e i checksum, anche una differenza invisibile cambia il risultato.
Un ordine affidabile per la risoluzione dei problemi è: preservare la fonte, ispezionare i byte, identificare la codifica dei caratteri prevista, decodificare con gestione esplicita degli errori e solo successivamente considerare la normalizzazione. MDN: btoa() spiega perché le chiamate dirette al browser btoa non sono adatte per testo Unicode arbitrario. I file binari dovrebbero ignorare completamente la decodifica del testo.