以下代码
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编码返回多余的字节。如果我们减少a-s,那么我们就没有多余的字节。如果我们采用更多的a-s,我们可以得到越来越多的字节。
为什么?
如何解决这个问题?
答案 0 :(得分:7)
你不能只获得支持数组并使用它。 ByteBuffers有一个capacity, position and a limit。
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
答案 1 :(得分:6)
您假设ByteBuffer
的支持数组恰好是保存内容的正确大小,但不一定如此。实际上,内容甚至不需要从数组的第一个字节开始!研究ByteBuffer
的API,您将了解正在发生的事情:内容从arrayOffset()
返回的值开始,limit()
返回结束。
答案 2 :(得分: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())));
这会产生您期望的结果。