Base64이 "한자를 깨는" 것으로 나타나는 경우 문제는 일반적으로 문자와 바이트 사이의 경계입니다. Base64은 시퀀스가 중국어 텍스트나 이모티콘을 나타내는지 알지 못합니다. 바이트를 보존합니다. 애플리케이션은 해당 바이트가 생성되고 해석되는 방식을 선택합니다.
바이트를 따르세요
中 문자는 U+4E2D입니다. UTF-8에서는 Base64 표현이 다음과 같은 바이트 E4 B8 AD를 사용합니다. 5Lit. 다른 문자 인코딩은 다른 바이트를 생성하므로 다른 Base64 값이 생성됩니다. 인코딩된 문자열을 비교하기 전에 양쪽 끝에서 UTF-8에 동의하세요.
const bytes = new TextEncoder().encode('中');
console.log([...bytes]); // [228, 184, 173]
console.log([...bytes].map(b => b.toString(16)).join(' ')); // e4 b8 ad
이모티콘은 또 다른 차이점을 보여줍니다: JavaScript '😊'.length 2개의 UTF-16 코드 단위이고 UTF-8 표현은 4바이트입니다. 두 숫자 모두 임의의 텍스트에서 사용자가 인식하는 문자의 개수가 아닙니다. 파일 및 전송 계산에 바이트 길이를 사용합니다.
교체 항목 표시
대체 문자 �는 이전 디코더가 이미 정보를 잃었음을 의미할 수 있습니다. 문자열에서 알 수 없는 바이트가 대체되고 해당 문자열이 다시 인코딩되면 일반적으로 원래 값을 재구성할 수 없습니다. 추가 변환을 수행하기 전에 원시 디코딩된 바이트 배열을 검사하십시오.
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.'); }
정규화는 별도의 작업입니다.
두 문자열은 서로 다른 유니코드 시퀀스를 포함하면서도 동일해 보일 수 있습니다. 악센트가 있는 문자 é는 미리 구성된 문자일 수도 있고 e 뒤에 결합 악센트가 올 수도 있습니다. UTF-8 및 Base64은 해당 차이를 올바르게 유지합니다. 애플리케이션에서 정규화된 텍스트를 원하는 경우 정규화 형식을 명시적으로 선택하고 인코딩하기 전에 적용하세요. 변경된 결과를 바이트 보존 복구라고 부르지 마십시오.
또한 결과가 다를 경우 보이지 않는 문자, 줄 끝 및 가능한 바이트 순서 표시를 확인하세요. 이는 실제 입력 바이트이며 반드시 인코더 버그는 아닙니다. 서명된 메시지와 체크섬의 경우 눈에 보이지 않는 차이라도 결과를 변경합니다.
신뢰할 수 있는 문제 해결 순서는 소스를 보존하고, 바이트를 검사하고, 예상되는 문자 인코딩을 식별하고, 명시적인 오류 처리를 통해 디코딩한 다음 정규화를 고려하는 것입니다. MDN: btoa() 직접 브라우저 btoa 호출이 임의의 유니코드 텍스트에 적합하지 않은 이유를 설명합니다. 바이너리 파일은 텍스트 디코딩을 완전히 우회해야 합니다.