Encoding Gossip: Unicode 및 UTF

4464 단어
http://caterpillar.onlyfun.net/Gossip/Encoding/UnicodeUTF.html
Big5는 첫 번째 비트 그룹의 어떤 범위를 사용해서 중문자인지 식별하기 때문에 저장할 수 있는 문자의 범위가 크게 줄어든다(약 1만 9천여 개). 만약에 당신이 저장한 문자가 Big5/MS950 인코딩 범위에 있지 않으면 어떻게 됩니까?Windows의 메모장 프로그램이라면 유니코드 형식으로 저장하라는 메시지가 나타납니다.'취소'를 누르면'새 파일 저장'대화상자가 나타납니다. 오른쪽 아래에'코딩'옵션이 있습니다. 밑에 유니코드, 유니코드 빅엔드, UTF-8 세 가지 옵션이 있습니다.Unicode는 The Unicode Consortium 비영리 조직이 주도하는 인코딩 표준으로 모든 글자에 유일한 인코딩을 제공한다. 표현할 때'U+'이후에 16진위 숫자를 연결하여 인코딩 숫자를 표시한다. 만약에 4개의 16진위제 숫자를 사용한다면 6만여 자를 표현할 수 있고 5진위제나 6개의 16진위제를 사용한다면 더 많은 글자를 표현할 수 있다.유니코드란 인코딩 방식을 가리킨다. 한 문자의 유니코드 인코딩은 고정적이지만 비트 그룹으로 표현하는 방법은 목적에 따라 서로 다른 실작 방식을 가리킨다. 유니코드의 실작 방식을 유니코드/UCS Transformation Format, 약칭 UTF라고 부른다.만약 당신이 직접 방재의 범례를 선택하여 "Unicode"저장을 선택하고 16진위 검사를 하면 "犛"라는 글자의 Unicode 인코딩은 U+7287입니다. Windows에 대한 수첩은 "Unicode"저장을 선택하면 두 개의 비트 그룹을 사용하여 저장합니다. Windows의 수첩은 "Unicode"옵션을 선택할 때 실제로는 UCS-2/UTF-16 저장을 사용합니다.처음에 두 개의 비트 그룹 (fffe) 은 파일을 식별하는 데 사용되는 비트 그룹 순서로 BOM (byteordermark) 이라고 불리며, 그 다음에 두 개의 비트 그룹을 사용하여 모든 유니코드 문자를 저장합니다.주의해야 할 것은'犛'라는 글자의 유니코드 인코딩은 U+7287이고 실제 저장할 때의 비트 그룹은 87, 72이다. 즉, Windows 수첩은'유니코드'를 선택하여 두 개의 상위 비트 그룹의 자료를 저장할 때 낮은 비트 그룹을 저장하고 높은 비트 그룹을 저장한다. 이런 저장 방식은 Little Endian을 채취하는 방식이다. 즉, Windows 수첩이'유니코드'를 선택할 때실제로는 UCS-2/UTF-16 Little Endian을 사용합니다.유니코드는 BOM 인코딩을 U+FEFF로 지정합니다.만약 파일을 읽는 시작의 BOM 순서가 0xfeff라면 파일은 Big Endian을 사용하고 파일을 읽는 시작의 BOM 순서가 0xfffe이면 파일은 Little Endian을 사용한다.Windows 메모장을 사용하여 저장할 때 옵션이 "Unicode big endian"이고 "犛"를 저장하면 결과는 다음과 같다. 알 수 있듯이 Unicode 파일의 두 비트 그룹은 f, ff로 이전의 f, f와 반대이며, "犛"라는 글자는 현재 72, 87로 저장되어 이전의 87, 72와 반대이다.만약 두 개의 상위 원조 자료를 저장할 때 먼저 고위원을 저장한 다음에 저위원 방식을 저장한다면 이런 저장 방식은 Big Endian을 채취하는 방식이다.이것은 어떤 영향이 있습니까?만약 아래의 자바 프로그램을 사용해서 "이 T는 e 테스트 t 테스트"가 저장된 텍스트 파일을 읽고, 텍스트 파일은 Windows 수첩에 있는'유니코드'옵션을 사용해서 저장한다면, 당신은 혼란스러운 코드를 얻을 수 있습니다.
import java.io.*;

public class Main {    
    public static void main(String[] args) throws Exception {
        FileInputStream in = new FileInputStream(args[0]);
        byte[] data = new byte[2];
        while(in.read(data) != -1) {
            int hex = ((data[0] << 8) | (data[1] & 0xFF)) & 0XFFFF;
            System.out.printf("%h ", hex); 
            System.out.println(new String(data, "UTF-16"));
        }
        in.close();
    }
}
C:\workspace>java Main sample.txt fffe 1990 ? 5400 ? 2f66 ? 6500 b50 등반?7300猀2c6e?7400 琀668a 暊
"이 T는 e 테스트 t 시험입니다"라는 텍스트 파일이 저장되어 있으면 Windows 수첩 "Unicode big endian"옵션을 사용하여 저장합니다. 즉, UCS-2/UTF-16 Big Endian을 사용하면 위의 프로그램은 정확한 텍스트 표시를 얻을 수 있습니다.
C:\workspace>java Main sample.txt feff 9019 이 54 T 662f는 65 e 500b 개 73 s 6e2c 측정 74 t 8a66 시험
이것은 JVM 자체가 Big Endian을 채취하는 방식으로 비트 그룹을 처리하기 때문이다. 하나의 텍스트 파일에 대해 Windows 수첩의'Unicode'옵션을 채취하여 저장하는 것은 Little Endian을 채취하는 것이다. 상기 프로그램으로 읽는 것은 당연히 난호일 것이다. 만약에 Windows 수첩의'Unicode'옵션에 저장된 텍스트 파일을 정확하게 읽으려면메서드 중 하나는 Java에서 비트 그룹 순서를 자동으로 변경하는 것입니다.
import java.io.*;

public class Main {    
    public static void main(String[] args) throws Exception {
        FileInputStream in = new FileInputStream(args[0]);
        byte[] data = new byte[2];
        byte[] bigEndian = new byte[2];
        while(in.read(data) != -1) {
            int hex = ((data[0] << 8) | (data[1] & 0xFF)) & 0XFFFF;
            System.out.printf("%h ", hex); 
            bigEndian[0] = data[1];
            bigEndian[1] = data[0];
            System.out.println(new String(bigEndian, "UTF-16"));
        }
        in.close();
    }
}
또는 UTF-16LE를 사용하도록 지정하는 것입니다. 예를 들어
import java.io.*;

public class Main {    
    public static void main(String[] args) throws Exception {
        FileInputStream in = new FileInputStream(args[0]);
        byte[] data = new byte[2];
        while(in.read(data) != -1) {
            int hex = ((data[0] << 8) | (data[1] & 0xFF)) & 0XFFFF;
            System.out.printf("%h ", hex); 
            System.out.println(new String(data, "UTF-16LE"));
        }
        in.close();
    }
}
이 두 프로그램은 모두 정확하게 읽을 수 있습니다. 예를 들어
C:\workspace>java Main sample.txt fffe 1990 이 5400T 2f66은 6500e b50개 7300s 2c6e 측정 7400t 668a 시험
UTF-8에 관해서는 다음 편에서 계속 설명하겠습니다.XD

좋은 웹페이지 즐겨찾기