一度にunicode、codepoint、コードポイント、UTFを明らかにする

5396 ワード

最近文字フィルタリングを処理し,下文字,unicode,コード点に関する知識を再検討したが,まず符号化の基本知識unicodeについて述べる.
unicode
Unicodeは、文字セット、符号化スキームなど、コンピュータ科学分野の業界標準です.コンピュータは8ビットの1バイトを採用して、1バイトの最大整数は255で、また中国語の1文字を表すのも足りないで、少なくとも2バイトを必要として、すべての文字の符号化を統一するために、unicodeは各言語の中の各文字のために統一して唯一の2進数の符号化を設定して、通常2バイトで1つの文字を表して、したがってunicodeは平面ごとに65535種類の異なる文字を組み合わせて、全部で17の平面を作ることができます.
英語記号は低8ビットしか使用できないため、高8ビットは永遠に0であるため、英語のテキストを保存する際に倍の空間を浪費することがあります.
例えば男の“漢”のunicode、javaの中で出力します
System.out.println("\u5B57");

UTF-8
unicodeがコンピュータにどのように格納されるかは、unicode文字セットでフォーマットを変換することです.つまり、私たちがよく見ているUTF-8、UTF-16などです.
UTF-8は、unicodeをバイト単位で符号化し、異なる範囲の文字に対して異なる長さの符号化を用いる.
Unicode
Utf-8
000000-00007F
0xxxxxxx
000080-0007FF
110xxxxx 10xxxxxx
000800-00FFFF
1110xxxx 10xxxxxx 10xxxxxx
010000-10FFFF
11110xxx10xxxxxx10xxxxxx10xxxxxx
JavaのStringオブジェクトはunicode符号化文字列です.
JAvaで知りたい文字のunicode符号化はInteger.toHexString()メソッド
        String str = " ";
        StringBuffer sb = new StringBuffer();
        char [] source_char = str.toCharArray();
        String unicode = null;
        for (int i=0;i

対応するutf-8コードは何ですか?
7 f 16は0800-FFFの間にあるので、3バイトテンプレート:1110 xxxxx 10 xxxxx 10 xxxxxxxを使います.7 f 16をバイナリと書く:0111 1111 0001 0110を3バイトテンプレートセグメント化方法で0111 111100 010110に分け、テンプレート中のxの代わりに1110011 10111100 10010110を得る.すなわち、「編」に対応するutf-8の符号化はe 7 bc 96であり、3バイトを占める
codepoint
unicodeの範囲は00000-10 FFFFから、charの範囲はuffffまでしかありません.つまり、標準的な2バイト形式は通常UCS-2と呼ばれています.Javaでは、charタイプはUTF-16符号化でコードユニットを記述していますが、unicodeが0 x 10000より大きい部分はどのようにcharで表されていますか.例えば、emoji:?
JAvaのcharタイプは2バイトを占めていますが、表示しますか?この表情には2つのcharが必要です.次のコードを見てください.
String testCode = "ab\uD83D\uDE03cd";
int length = testCode.length();
int count = testCode.codePointCount(0, testCode.length());
//length=6
//count=5

3番目と4番目の文字を合わせて表しますか?コードポイントです.コードポイントごとに判断したい場合は、このように書くことができます.
        String testCode = "ab\uD83D\uDE03cd";
        int cpCount = testCode.codePointCount(0, testCode.length());
        for(int index = 0; index < cpCount; ++index) {
            //   i      
            int i = testCode.offsetByCodePoints(0, index);
            int codepoint = testCode.codePointAt(i);
        }
      //  
      i:0 index: 0 codePoint: 97
      i:1 index: 1 codePoint: 98
      i:2 index: 2 codePoint: 128515
      i:4 index: 3 codePoint: 99
      i:5 index: 4 codePoint: 100

つまりcodePointindexに従って文字を取り、0はaを取り、1はbを取り、2はuD 83 DuDE 03を取ります.3 c、4 dを取る.Stringのindexに従って文字を取り、0はa、1はb、2はuD 83 D、3はuDE 03、4はc、5はdを取ります.これがcodePointIndexとcharのindexの違いです.
codePointを取るとunicode値に従って文字のフィルタリングなどの操作ができます.
unicode値で文字をフィルタリングしたり、正規表現で文字をフィルタリングしたり、ホワイトリストが必要な場合は、どのように実現すればいいのでしょうか.
実はunicodeフィルタリングと正規表現フィルタリングは衝突していないので、自分で自分のフィルタリングを実現すればいいのですが、フィルタリングホワイトリストに参加する必要があると複雑になり、直接フィルタリングできないので、ホワイトリストのindexかどうかを先に検証する必要があります.
私の考え方はホワイトリストcharのindexを記録することであり、正規表現やその他のフィルタリング方式で違反charのindexを得ることができ、unicodeブラックリストのcodepointIndexはcharのindexに変換することができ、codePontのindexを取得する際に現在の文字が単char文字か双char文字かを判断することができ、双char文字には2つの下付き文字を追加する必要があり、方法は以下の通りである.
        //  unicode            
        int codepoint = testCode.codePointAt(i);
        // unicode    char  
        char[] chars = Character.toChars(codepoint);
        charIndexs.add(pointIndex);
        if (chars.length > 1) {
            //     char  ,  index     i+1
           charIndexs.add(pointIndex + 1);
        }
     

//例String str=「abuD 83 DuDE 03漢字」emojiを処理したくて、あの記録の下の札は2、3で、最後に白いリストの下の札と比較した後に統一的に削除します
charがペアなのか単一なのかを区別する方法
前の例abuD 83 DuDE 03 cdについて、「61uD 83 DuDE 0」64プログラムがどのようにしてuD 83 DuDE 03を文字に解析したのか.これは、UTF-16からのSurrogateという概念が必要です.
UTF-16は16 bit最大符号化65536ですが、65536より大きい場合はどのように符号化しますか?Unicode標準制定チームが考案した方法は、この65536個の符号化から2048個を取り出し、「Surrogates」と規定し、65536より番号の大きい文字を表す2つを1組にすることだ.番号U+D 800からU+DFFまでの規定は「High Surrogates」で1024個.番号がU+DC 00からU+DFFまでの規定は「Low Surrogates」で1024個.彼らの組み合わせが現れると、1048576の文字を多く表すことができます.
Stringを見てcodePointAtという方法で、
    static int codePointAtImpl(char[] a, int index, int limit) {
        char c1 = a[index];
        if (isHighSurrogate(c1) && ++index < limit) {
            char c2 = a[index];
            if (isLowSurrogate(c2)) {
                return toCodePoint(c1, c2);
            }
        }
        return c1;
    }

中には2つの方法isHighSurrogate,isLowSurrogateがある.第1の方法は、高エージェントエントリコードユニットであるか否かを判断し、すなわち'uD 800'と'uDFF'との間であり、第2の方法は、低エージェントエントリコードユニットであるか否かを判断し、すなわち'uDC 00'と'uDFF'との間である.
codePointAtImplメソッドは、現在のcharが高エージェントエントリコードユニットであり、次が低エージェントエントリコードユニットであると判断し、この2つのcharがcodepointである.
unicodeでUTF-16を回す方法をもう一度見てみましょう
U<0 x 10000であれば、UのUTF-16符号化はUに対応する16ビットの符号なし整数である(書きやすいため、以下、16ビットの符号なし整数をWORDと記す).U≧0 x 10000であれば、まずU'=U-0 x 10000を計算し、その後、U'をバイナリ形式として書く:yyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
それともU+1 F 603でこれ?例として、U'=U-0 x 100000=F 603を2進法として書くと1111011000000011となり、20ビット未満の前に0を補い、0000111101-10000011となり、yとxを置き換えると110110000011110111011110000011となり、最後にUTF-16符号化が[d 83 d,de 03]となる.