9

次のコード

public class CharsetProblem {
public static void main(String[] args) {
    //String str = "aaaaaaaaa";
    String str = "aaaaaaaaaa";
    Charset cs1 = Charset.forName("ASCII");
    Charset cs2 = Charset.forName("utf8");

    System.out.println(toHex(cs1.encode(str).array()));
    System.out.println(toHex(cs2.encode(str).array()));

}

public static String toHex(byte[] outputBytes) {

    StringBuilder builder = new StringBuilder();

    for(int i=0; i<outputBytes.length; ++i) {
        builder.append(String.format("%02x", outputBytes[i]));
    }

    return builder.toString();
}
}

戻り値

61616161616161616161
6161616161616161616100

つまり、utf8 エンコーディングは余分なバイトを返します。as を少なくすると、余分なバイトはなくなります。より多くの余分なバイトを取得できます。

なんで?

これを回避するにはどうすればよいですか?

4

3 に答える 3

8

バッキング配列を取得して使用することはできません。ByteBuffers には、容量、位置、および制限があります

System.out.println(cs1.encode(str).remaining());
System.out.println(cs2.encode(str).remaining());

生成:

10
10

代わりにこれを試してください:

public static void main(String[] args) {
  //String str = "aaaaaaaaa";
  String str = "aaaaaaaaaa";
  Charset cs1 = Charset.forName("ASCII");
  Charset cs2 = Charset.forName("utf8");

  System.out.println(toHex(cs1.encode(str)));
  System.out.println(toHex(cs2.encode(str)));
}

public static String toHex(ByteBuffer buff) {
  StringBuilder builder = new StringBuilder();
  while (buff.remaining() > 0) {
    builder.append(String.format("%02x", buff.get()));
  }
  return builder.toString();
}

それは期待されるものを生成します:

61616161616161616161
61616161616161616161
于 2012-07-03T21:37:53.803 に答える
7

ByteBuffera のバッキング配列がコンテンツを保持するのに正確なサイズであると想定していますが、必ずしもそうとは限りません。実際、コンテンツは配列の最初のバイトから始まる必要さえありません! の API を調べるByteBufferと、何が起こっているかがわかります。内容は によって返される値で始まり、 によって返される値arrayOffset()で終わりlimit()ます。

于 2012-07-03T21:37:40.713 に答える
2

答えはすでに与えられていますが、同じ問題に遭遇したので、詳細を提供すると役立つと思います。

呼び出しによって返されるバイト配列、cs1.encode(str).array()またはcs2.encode(str).array()その時点で ByteBuffer に割り当てられている配列全体への参照を返します。アレイの容量は、実際に使用される容量よりも大きい場合があります。使用済み部分のみを取得するには、次のようにする必要があります。

ByteBuffer bf1 = cs1.encode(str);
ByteBuffer bf2 = cs2.encode(str);
System.out.println(toHex(Arrays.copyOf(bf1.array(), bf1.limit())));
System.out.println(toHex(Arrays.copyOf(bf2.array(), bf2.limit())));

これにより、期待どおりの結果が得られます。

于 2014-01-20T10:55:52.543 に答える