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 编码返回多余的字节。如果我们取less 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

您假设 a 的支持数组ByteBuffer恰好是容纳内容的正确大小,但不一定。事实上,内容甚至不需要从数组的第一个字节开始!研究一下 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 回答