9

次のコードを検討してください。

byte aBytes[] = { (byte)0xff,0x01,0,0,
                  (byte)0xd9,(byte)0x65,
                  (byte)0x03,(byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07,
                  (byte)0x17,(byte)0x33, (byte)0x74, (byte)0x6f,
                   0, 1, 2, 3, 4, 5,
                   0 };
String sCompressedBytes = new String(aBytes, "UTF-16");
for (int i=0; i<sCompressedBytes.length; i++) {
    System.out.println(Integer.toHexString(sCompressedBytes.codePointAt(i)));
}

次の誤った出力を取得します。

ff01, 0, fffd, 506, 717, 3374, 6f00, 102, 304, 500.

ただし、0xd9入力データの を に変更する0x9dと、次の正しい出力が得られます。

ff01, 0, 9d65, 304, 506, 717, 3374, 6f00, 102, 304, 500.

0xd9この機能は、バイトが上位サロゲート Unicode マーカーであるという事実によるものだと認識しています。

質問: Java Unicode 文字列内のサロゲート バイト ( 0xd800to ) をフィード、識別、および抽出する方法はありますか? ありがとう0xdfff

4

2 に答える 2

5

Java Unicode 文字列でサロゲート バイト (0xd800 から 0xdfff) をフィード、識別、および抽出する方法はありますか?

誰も言及していないので、Characterクラスにはサロゲート ペアを操作するためのメソッドが含まれていることを指摘しておきます。例: isHighSurrogate(char)codePointAt(CharSequence, int)toChars(int)。これは、述べられている問題のポイント以外にあることを認識しています。

new String(aBytes, "UTF-16");

これは、入力データを変換するデコード操作です。選択したデコード操作では、入力が 0xfe 0xff または 0xff 0xfe (バイト オーダー マーク) で始まる必要があるため、合法ではないと確信しています。さらに、UTF-16 は可変幅エンコーディングであるため、考えられるすべてのバイト値を正しくデコードできるわけではありません。

任意のバイトを String に、またはその逆に対称変換する場合は、すべてのバイト値が有効な文字であるため、8 ビットのシングルバイト エンコーディングを使用することをお勧めします。

Charset iso8859_15 = Charset.forName("ISO-8859-15");
byte[] data = new byte[256];
for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
  data[i - Byte.MIN_VALUE] = (byte) i;
}
String asString = new String(data, iso8859_15);
byte[] encoded = asString.getBytes(iso8859_15);
System.out.println(Arrays.equals(data, encoded));

注: 文字数はバイト数と等しくなります (データのサイズが 2 倍になります)。結果の文字列は必ずしも印刷可能になるとは限りません (制御文字の束を含む可能性があります)。

ただし、私は Jon と一緒です。任意のバイト シーケンスを Java 文字列に入れることは、ほとんどの場合、悪い考えです。

于 2009-06-09T10:08:09.467 に答える