2013-09-10 14 views

답변

39

UTF-8 유니 인코딩 로직은 기본적으로 : 문자 당

  • 최대 4 바이트를 사용할 수있다. 가능한 가장 적은 수의 바이트가 사용됩니다.
  • U + 007F까지의 문자는 단일 바이트로 인코딩됩니다.
  • 멀티 바이트 시퀀스의 경우 첫 번째 바이트의 첫 번째 1 비트 수는 문자의 바이트 수를 제공합니다. 첫 번째 바이트의 나머지 비트는 문자의 비트를 인코딩하는 데 사용할 수 있습니다.
  • 연속 바이트는 10으로 시작하고 나머지 6 비트는 문자의 비트를 인코딩합니다. 여기

내가 UTF-8로 자바 스크립트 UTF-16 문자열을 인코딩하는 동안 다시 쓴 함수의 : 문제는 입력으로 DOMString에 관한 가정

function toUTF8Array(str) { 
    var utf8 = []; 
    for (var i=0; i < str.length; i++) { 
     var charcode = str.charCodeAt(i); 
     if (charcode < 0x80) utf8.push(charcode); 
     else if (charcode < 0x800) { 
      utf8.push(0xc0 | (charcode >> 6), 
         0x80 | (charcode & 0x3f)); 
     } 
     else if (charcode < 0xd800 || charcode >= 0xe000) { 
      utf8.push(0xe0 | (charcode >> 12), 
         0x80 | ((charcode>>6) & 0x3f), 
         0x80 | (charcode & 0x3f)); 
     } 
     // surrogate pair 
     else { 
      i++; 
      // UTF-16 encodes 0x10000-0x10FFFF by 
      // subtracting 0x10000 and splitting the 
      // 20 bits of 0x0-0xFFFFF into two halves 
      charcode = 0x10000 + (((charcode & 0x3ff)<<10) 
         | (str.charCodeAt(i) & 0x3ff)); 
      utf8.push(0xf0 | (charcode >>18), 
         0x80 | ((charcode>>12) & 0x3f), 
         0x80 | ((charcode>>6) & 0x3f), 
         0x80 | (charcode & 0x3f)); 
     } 
    } 
    return utf8; 
} 
+0

결과가'unescape (encodeURIComponent())와 같지 않습니다. '. http://stackoverflow.com/a/18729536/2408835 –

+2

@donkaka'for' 루프 다음에'arr'과 비교해서 일치해야합니다. http://jsfiddle.net/3Uz8n/ –

+0

http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt와 비슷하게 잘 보이지 않는 4 바이트 문자열 , CJK Unified Extension B의 문자. –

23

자바 스크립트 Stringstored in UTF-16입니다. UTF-8을 얻으려면 String을 직접 변환해야합니다.

encodeURIComponent()을 URL과 인코딩 된 UTF-8 바이트로 출력하고, unescapementioned on ecmanaut으로 출력하는 것도 한 가지 방법입니다.

var utf8 = unescape(encodeURIComponent(str)); 

var arr = []; 
for (var i = 0; i < utf8.length; i++) { 
    arr.push(utf8.charCodeAt(i)); 
} 
+0

감사합니다. 작동합니다. 하지만이 유니 코드를 utf8 바이트 코드 변환으로 코딩하는 방법을 알고 싶습니다. 그것에 관한 기사를 제게 링크 해 주시겠습니까? 나는 아무 것도 찾지 못했다 –

+0

@donkaka 나는 나의 지위에 하나와 연결되어있다. http://ecmanaut.blogspot.com/2006/07/encoding-decoding-utf8-in-javascript.html. 수동으로 코드 단위로 변환하고 싶습니까? –

+0

예. encodeURIComponent는 잘 작동하지만 UTF8 바이트 코드가 어떻게 생성되는지 이해하고 싶습니다. –

5

과 목표는를 얻는 것입니다 배열, 문자열로 해석하는 경우 (예 : 디스크에있는 파일에 기록 된) 것으로, UTF-8 인코딩 것 :

이 방법이 나열되지 않은 경우 거의 모든 최신 브라우저 support Typed Arrays, 그것은 부끄러워 할 줄 이제

:

  • W3C에 따르면, 파일 API를 지원하는 소프트웨어가 의 Blob 생성자의 DOMString의를 받아 들여야한다 (참조 : String encoding when constructing a Blob를)
  • 물방울은 파일 리더의 .readAsArrayBuffer() 기능을 사용하여 ArrayBuffer로 변환 할 수 있습니다
  • DataView를을 사용하거나 파일 리더에 의해 판독 된 버퍼를 가지는 형식화 된 배열를 구성, 하나는 ArrayBuffer
  • 의 모든 단일 바이트에 액세스 할 수 있습니다

예 : JSFiddle에 그와

// Create a Blob with an Euro-char (U+20AC) 
var b = new Blob(['€']); 
var fr = new FileReader(); 

fr.onload = function() { 
    ua = new Uint8Array(fr.result); 
    // This will log "3|226|130|172" 
    //     E2 82 AC 
    // In UTF-16, it would be only 2 bytes long 
    console.log(
     fr.result.byteLength + '|' + 
     ua[0] + '|' + 
     ua[1] + '|' + 
     ua[2] + '' 
    ); 
}; 
fr.readAsArrayBuffer(b); 

플레이. 나는 이것을 아직 벤치마킹하지 않았지만 이것이 큰 DOMString을 입력으로하는 것이 효율적이라고 상상할 수 있습니다.

+0

이것은 아주 좋습니다.JS에서 미친듯한 비트 - twiddling에 대한 필요성, 그냥 똑바로 Blob 생성자에 전달합니다. 감사! –

7

Google 클로저 라이브러리에는 UTF-8 및 바이트 배열로 /에서 변환 할 수있는 기능이 있습니다. 전체 라이브러리를 사용하지 않으려면 here에서 기능을 복사 할 수 있습니다.완성도를 들어, 코드가 UTF-8 바이트 배열을 문자열로 변환하는 것은 :

goog.crypt.stringToUtf8ByteArray = function(str) { 
    // TODO(user): Use native implementations if/when available 
    var out = [], p = 0; 
    for (var i = 0; i < str.length; i++) { 
    var c = str.charCodeAt(i); 
    if (c < 128) { 
     out[p++] = c; 
    } else if (c < 2048) { 
     out[p++] = (c >> 6) | 192; 
     out[p++] = (c & 63) | 128; 
    } else if (
     ((c & 0xFC00) == 0xD800) && (i + 1) < str.length && 
     ((str.charCodeAt(i + 1) & 0xFC00) == 0xDC00)) { 
     // Surrogate Pair 
     c = 0x10000 + ((c & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF); 
     out[p++] = (c >> 18) | 240; 
     out[p++] = ((c >> 12) & 63) | 128; 
     out[p++] = ((c >> 6) & 63) | 128; 
     out[p++] = (c & 63) | 128; 
    } else { 
     out[p++] = (c >> 12) | 224; 
     out[p++] = ((c >> 6) & 63) | 128; 
     out[p++] = (c & 63) | 128; 
    } 
    } 
    return out; 
}; 
+0

링크를 통해 404. –

+0

Google이 github에 클로저를 이전했습니다. 링크를 업데이트했습니다 (기능 구현이 변경됨에 따라 코드 스 니펫도 업데이트 됨). – optevo

3

새로운 Encoding API은 (입력 배열을 사용하여) 모두 인코딩 및 디코딩 UTF-8 쉽게 당신을 수 있도록 보인다

var encoded = new TextEncoder("utf-8").encode("Γεια σου κόσμε"); 
var decoded = new TextDecoder("utf-8").decode(encoded); 

console.log(encoded, decoded); 

브라우저 지원 isn't too bad, 그러나 Microsoft Edge에서 현재 지원되지 않습니다. IE11 및 Edge에서 작동해야하는 polyfill이 있습니다.

1

FileReader을 사용하여 그대로 문자열을 저장할 수 있습니다.

문자열을 blob에 저장하고 을 호출하십시오. readAsArrayBuffer() 그런 다음 onload-event는 Uint8Array에서 변환 할 수있는 배열 버퍼를 생성합니다. 불행히도이 호출은 비동기입니다.

이 작은 기능을 사용하면 도움이 될 것입니다 :이 같은

function stringToBytes(str) 
{ 
    let reader = new FileReader(); 
    let done =() => {}; 

    reader.onload = event => 
    { 
     done(new Uint8Array(event.target.result), str); 
    }; 
    reader.readAsArrayBuffer(new Blob([str], { type: "application/octet-stream" })); 

    return { done: callback => { done = callback; } }; 
} 

전화를 :

stringToBytes("\u{1f4a9}").done(bytes => 
{ 
    console.log(bytes); 
}); 

출력 :[240, 159, 146, 169]

설명 :

자바 스크립트를 사용하여 UTF-16 및 대리 쌍 t o 유니 코드 문자를 메모리에 저장합니다. 유니 코드 문자를 원시 2 진수 바이트 스트림으로 저장하려면 인코딩이 필요합니다. 보통 대부분의 경우 UTF-8이이 용도로 사용됩니다. enconding을 사용하지 않으면 유니 코드 문자를 저장할 수 없으며 ASCII는 0x7f까지만 저장할 수 있습니다.

FileReader.readAsArrayBuffer()는 UTF-8을 사용합니다.

관련 문제