2012-07-03 67 views
7

下面的代码Java错误?为什么utf8编码中额外的零字节?

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编码返回过量字节。如果我们减少一个-s,那么我们就不会有多余的字节。如果我们采取更多的a-s,我们可以得到越来越多的多余字节。

为什么?

如何解决这个问题?

回答

6

你不能只获得支持数组并使用它。 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 
6

假设ByteBuffer的支持阵列恰好是保存内容的正确大小,但并不一定。实际上,内容甚至不需要从数组的第一个字节开始!研究ByteBuffer的API,你就会明白发生了什么:内容从arrayOffset()返回的值开始,返回的结束。

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()))); 

这会产生您期望的结果。

相关问题