UTF-16을 정의하는 ietf문서#

http://www.ietf.org/rfc/rfc2781.txt

UTF-16 정의#

UTF-16은 버전 3.0에서 유니코드 표준으로 지정되었다.
  • 0x10000 ( 16진수로는 65536, 2진수로는 11111111 11111111 + 1 ) 보다 작은 문자들은 한개의 16비트 숫자로 표기된다.
  • 0x10000 와 0x10FFFF 사이의 값을 가지는 문자들은 0xD800 와 0xDBFF 사이의 값을 가지는 16비트 숫자와 0xDC00 와 0xDFFF 사이의 값을 가지는 16비트 숫자로 표기된다.
여기서 0xD800(2진수로 11011000 00000000, 10진수로 55296) 와 0xDBFF(2진수로 11011011 11111111, 10진수로 56319) 사이의 값은 high-half zone 또는 high surrogate area 라고 불린다. 여기서 0xDC00(2진수로 11011100 00000000, 10진수로 56320) 와 0xDFFF(2진수로 11011111 11111111, 10진수로 57343) 사이의 값은 low-half zone 또는 low surrogate area 라고 불린다. 간단히 보면 아래와 같다.
Bit
31                24|23             16|15                8|7               0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0 0 0 0 0 0 0|0 0 0 z z z z z|x x x x x x y y|y y y y y y y y|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|15               8|7                  0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|1 1 0 1 1 0 Z Z|Z Z x x x x x x|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|15             8|7                0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|1 1 0 1 1 1 y y|y y y y y y y y|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

  • 0x10FFFF 보다 큰 값은 UTF-16으로 인코딩 할수 없다.
0xD800 와 0xDFFF 사이의 값들이 특별히 UTF-8 를 사용하도록 예약되어 있다.

UTF-16 인코딩/디코딩#

인코딩#

  • 0x10000 보다 작다면 16 비트 unsigned 정수로 인코딩되고 종료된다.
  • 0x10000 을 빼서 0xFFFFF 보다 작거나 같다면 20비트 문자로 표기할 수 있다.
여기서 두개의 unsigned 정수를 초기화하고 각각을 10비트씩 할당한다. 0x10000 를 뺀 값을 U' 라고 할때 다음과 같은 형태가 된다.
U' = yyyyyyyyyyxxxxxxxxxx
W1 = 110110yyyyyyyyyy
W2 = 110111xxxxxxxxxx

디코딩#

자바를 이용해 UTF-16 으로 문자을 추출해보면 대상이 되는 문자는 2개의 char로 추출이 된다. 각각을 W1, W2 라고 할때.
  • W1 < 0xD800 또는 W1 > 0xDFFF 라면 U는 W1이 된다.
  • W1이 0xD800 와 0xDBFF 사이의 값이 아니라면 에러이다.
  • W2가 없거나 W2가 0xDC00 와 0xDFFF 사이의 값이라면 에러이다.
  • 20비트의 unsigned 정수 U' 로 만들고 W1, W2에서 10비트씩 값을 가져와서 만든다.
  • 실제 값을 얻기 위해 0x10000 를 더하고 값을 추출한다.
public String encode(String content, int start, int end) {
	StringBuilder sgml = new StringBuilder();
	char chr, chr2;
	int ord = 0;

	for (int i = 0; i < content.length(); i++) {
		chr = content.charAt(i);
		ord = (int) chr;
		if ( (int) chr > 55296 || (int) chr < 57343 ) {
			if ( (int) chr > 55296 && (int) chr < 56319 ) {
				chr2 = content.charAt(i+1);
				if ( (int) chr2 > 56320 && (int) chr < 57343) {
					ord = (int) ((int) (chr & 1023) << 10) + (int) (chr2 & 1023) + 65536;
					i = i + 1;
				} else {
					//error
				}
			} else {
				//error
			}
		}
		if (start <= ord && ord <= end) {
			sgml.append(prefix + ord + suffix);
		} else {
			sgml.append(chr);
		}
	}
	return sgml.toString();		
}

public String decode(String sgml) {
	StringBuilder content = new StringBuilder();
	StringBuilder buffer  = new StringBuilder();
	int ord = 0, chr = 0, status = 0;

	for (int i = 0; i < sgml.length(); i++) {
		ord = (int)sgml.charAt(i);

		// & 일 경우
		if (ord == 38) {
			status = 1;
			buffer.append((char) ord);
		// # 일 경우
		} else if (status == 1 && ord == 35) {
			status = 2;
			buffer.append((char) ord);
		// 0-9 일 경우
		} else if ((status == 2 || status == 3) && ( 47 < ord  && ord < 58 ) ) {
			status = 3;
			buffer.append((char) ord);
		// ; 일 경우
		} else if (status == 3 && ord == 59 ) {
			status = 0;
			chr = Integer.parseInt(buffer.substring(2, buffer.length()));
			if ( chr < 65536 ) {
				content.append((char) chr);
			} else {
				chr = chr - 65536;
				content.append((char) ((chr >> 10) | 55296));
				content.append((char) ((chr & 1023) | 56320));
			}
			buffer.delete(0, buffer.length());
		// 아무것도 아닐경우
		} else {
			status = 0;
			content.append(buffer);
			buffer.delete(0, buffer.length());
		}
	}
	
	return content.toString();
}

Add new attachment

Only authorized users are allowed to upload new attachments.
« This page (revision-7) was last changed on 01-Feb-2009 23:05 by DongGukLee  
G’day (anonymous guest) My Prefs

Referenced by
Basic

JSPWiki v2.8.4