2012-07-03 15 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エンコーディングは、過剰バイトを返します。より少ないa-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()によって返された値から始まり、最後は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()))); 

関連する問題