Base64 och UTF-8: diagnostisera kinesisk text, emoji och ersättningstecken

Spåra text genom Unicode och UTF-8 byte, särskilj avkodningsfel från normalisering och bevara ogiltig binär indata.

När Base64 verkar "bryta kinesiska" är problemet vanligtvis gränsen mellan tecken och byte. Base64 vet inte att en sekvens representerar kinesisk text eller emoji. Det bevarar bytes; applikationen väljer hur dessa bytes produceras och tolkas.

Följ byten

Tecknet 中 är U+4E2D. I UTF-8 använder den byte E4 B8 AD, vars Base64 representation är 5Lit. En annan teckenkodning ger olika byte och därför ett annat Base64 värde. Kom överens om UTF-8 i båda ändarna innan du jämför kodade strängar.

const bytes = new TextEncoder().encode('中');
console.log([...bytes]); // [228, 184, 173]
console.log([...bytes].map(b => b.toString(16)).join(' ')); // e4 b8 ad

Emoji illustrerar en annan distinktion: JavaScript '😊'.length är två UTF-16-kodenheter, medan dess UTF-8-representation har fyra byte. Ingendera siffran ensam är en räkning av synliga användaruppfattade tecken i godtycklig text. Använd bytelängd för fil- och transportberäkningar.

Gör ersättningen synlig

Ersättningstecknet � kan betyda att en tidigare avkodare redan har förlorat information. När väl okända bytes har ersatts i en sträng och den strängen kodats om, kan de ursprungliga värdena i allmänhet inte rekonstrueras. Inspektera den råavkodade bytematrisen innan du gör ytterligare omvandlingar.

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.'); }

Normalisering är en separat operation

Två strängar kan se identiska ut samtidigt som de innehåller olika Unicode-sekvenser. Den accentuerade bokstaven é kan vara ett förkomponerat tecken eller ett e följt av en kombinerande accent. UTF-8 och Base64 behåller den skillnaden korrekt. Om din applikation vill ha normaliserad text, välj en normaliseringsform explicit och använd den innan du kodar; kalla aldrig ett ändrat resultat för en bytebevarande reparation.

Kontrollera även osynliga tecken, radslut och en möjlig byte-ordningsmarkering när resultaten skiljer sig. Dessa är riktiga indatabytes, inte nödvändigtvis kodarbuggar. För signerade meddelanden och kontrollsummor ändrar även en osynlig skillnad resultatet.

En tillförlitlig felsökningsordning är: bevara källan, inspektera bytes, identifiera den förväntade teckenkodningen, avkoda med explicit felhantering och överväg bara normalisering. MDN: btoa() förklarar varför direkta btoa-anrop i webbläsaren är olämpliga för godtycklig Unicode-text. Binära filer bör kringgå textavkodning helt.