1

バイト ストリーム (文字を表す) とストリームのエンコーディングが与えられた場合、文字のコード ポイントを取得するにはどうすればよいでしょうか?

InputStreamReader r = new InputStreamReader(bla, Charset.forName("UTF-8"));
int whatIsThis = r.read(); 

上記のスニペットで read() によって返されるものは何ですか? それはユニコードのコードポイントですか?

4

2 に答える 2

2

Reader.read()キャスト可能な値を返しcharます。使用可能なデータがなくなった場合は-1を返します。

Acharは、(暗黙的に)UTF-16BEエンコーディングの16ビットコードユニットです。このエンコーディングは、単一ので基本的な多言語面の文字を表すことができcharます。補足範囲は、2つのcharシーケンスを使用して表されます。

このCharacter型には、UTF-16コード単位をUnicodeコードポイントに変換するためのメソッドが含まれています。

char2つのsを必要とするコードポイントは、シーケンスから2つの連続した値を渡すときに、 isHighSurrogateisLowSurrogateを満たします。codePointAtメソッドを使用して、コードユニットシーケンスからコードポイントを抽出できます。コードポイントからUTF-16コードユニットまで作業するための同様の方法があります。


コードポイントストリームリーダーのサンプル実装:

import java.io.*;
public class CodePointReader implements Closeable {
  private final Reader charSource;
  private int codeUnit;

  public CodePointReader(Reader charSource) throws IOException {
    this.charSource = charSource;
    codeUnit = charSource.read();
  }

  public boolean hasNext() { return codeUnit != -1; }

  public int nextCodePoint() throws IOException {
    try {
      char high = (char) codeUnit;
      if (Character.isHighSurrogate(high)) {
        int next = charSource.read();
        if (next == -1) { throw new IOException("malformed character"); }
        char low = (char) next;
        if(!Character.isLowSurrogate(low)) {
          throw new IOException("malformed sequence");
        }
        return Character.toCodePoint(high, low);
      } else {
        return codeUnit;
      }
    } finally {
      codeUnit = charSource.read();
    }
  }

  public void close() throws IOException { charSource.close(); }
}
于 2013-01-08T21:05:02.227 に答える
2

Unicode コード ポイントではなく、UTF-16 コード単位を読み取ります。0xFFFF 未満のコード ポイントには違いはありませんが、0xFFFF を超えるコード ポイントはそれぞれ 2 つのコード単位で表されます。これは、16 ビットでは 0xFFFF を超える値を持つことができないためです。

この場合もそうです:

byte[] a = {-16, -96, -128, -128}; //UTF-8 for  U+20000

ByteArrayInputStream is = new ByteArrayInputStream(a);
InputStreamReader r = new InputStreamReader(is, Charset.forName("UTF-8"));
int whatIsThis = r.read();
int whatIsThis2 = r.read();
System.out.println(whatIsThis); //55360 not a valid stand alone code point 
System.out.println(whatIsThis2); //56320 not a valid stand alone code point

サロゲート値を使用して、それらをまとめて次を取得します0x20000

((55360 - 0xD800) * 0x400) + (56320 - 0xDC00) + 0x10000 == 0x20000

UTF-16 の仕組みの詳細: http://en.wikipedia.org/wiki/UTF-16

于 2013-01-08T19:58:56.110 に答える