2012-07-03 2 views
7

다음 코드자바 버그? utf8 인코딩에서 여분의 0 바이트가 필요한 이유는 무엇입니까?

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 인코딩 초과 바이트를 리턴

. 우리가 더 적게 잡으면 초과 바이트가 없습니다. 우리가 더 많은 것을 갖게되면 초과 바이트를 점점 더 많이 얻을 수 있습니다.

왜?

어떻게 해결할 수 있습니까?

답변

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()에 의해 반환 된 값에서 시작하고 끝은 limit()에서 반환됩니다.

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

이렇게하면 예상 한 결과가 나옵니다.

관련 문제