2011-05-25 9 views
11

Bunun çok genel bir soru olduğunu biliyorum ama kızmaya başladım. Java'dan Windows 1252'den UTF8'ye dönüştürme: CharsetDecoder/Encoder ile boş karakterler

Bu kodu kullandı:

String ucs2Content = new String(bufferToConvert, inputEncoding);   
     byte[] outputBuf = ucs2Content.getBytes(outputEncoding);   
     return outputBuf; 

Ama bunu CharsetDecoder ve CharsetEncoder (muhtemelen hedef kodlama dışında bazı karakteriyle içeriğe sahip) kullanmak daha iyidir okuyun. Sadece bu kodu yazdım ama bu bazı sorunları var: null karakteri dizisi tampon

// Create the encoder and decoder for Win1252 
Charset charsetInput = Charset.forName(inputEncoding); 
CharsetDecoder decoder = charsetInput.newDecoder(); 

Charset charsetOutput = Charset.forName(outputEncoding); 
CharsetEncoder encoder = charsetOutput.newEncoder(); 

// Convert the byte array from starting inputEncoding into UCS2 
CharBuffer cbuf = decoder.decode(ByteBuffer.wrap(bufferToConvert)); 

// Convert the internal UCS2 representation into outputEncoding 
ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(cbuf)); 
return bbuf.array(); 

Nitekim bu kod ekler !!!!!

Birisi bana sorunun nerede olduğunu söyleyebilir mi? Java'da kodlamayı dönüştürme konusunda çok yetenekli değilim.

Java'da kodlamayı dönüştürmenin daha iyi bir yolu var mı?

cevap

7

Senin sorunun ByteBuffer.array() destek ByteBuffer mağaza ve destek dizinin geçerli aralık değil bir kopya olarak kullanılan diziye doğrudan başvuru verir olmasıdır. bbuf.limit()'a (cevabında Peter yaptığı gibi) uymalısınız ve dizi içeriğini 0 dizisinden bbuf.limit()-1'a kullanmalısınız.

Destek dizisindeki fazladan 0 değerinin nedeni, sonuçta oluşan ByteBuffer'ın CharsetEncoder tarafından nasıl oluşturulduğuna dair hafif bir kusurdur. Her CharsetEncoder, UCS2 enkoderi için basit ve doğru (2 byte/char) gibi görünen "karakter başına ortalama bayt" a sahiptir. Bu sabit değere uyarak, CharsetEncoder başlangıçta bir ByteBuffer'ı "karakter başına dize uzunluğu * ortalama bayt" baytı ile ayırır; 10 karakter uzunluğunda bir dize için 20 bayt. Ancak UCS2 CharsetEncoder, 2 bayt kaplayan bir BOM (bayt sırası işareti) ile başlar, böylece 10 karakterden sadece 9'u, ByteBuffer'a ayrılır. CharsetEncoder taşmayı algılar ve 2 * n + 1 (n byteBuffer'ın orijinal uzunluğudur) uzunluğunda yeni bir ByteBuffer atar, bu durumda 2 * 20 + 1 = 41 byte. Kalan karakteri kodlamak için 21 yeni bayttan yalnızca 2'si gerektiğinden, bbuf.array()'dan aldığınız dizi 41 bayt uzunluğa sahip olur, ancak bbuf.limit() yalnızca ilk 22 girdinin gerçekten kullanıldığını gösterir.

+0

Teşekkürler, muhtemelen birkaç saat hayal kırıklığı kurtardınız – pepsi

4

null karakter dizisini nasıl aldığınızdan emin değilim. Deneyin bu

String outputEncoding = "UTF-8"; 
Charset charsetOutput = Charset.forName(outputEncoding); 
CharsetEncoder encoder = charsetOutput.newEncoder(); 

// Convert the byte array from starting inputEncoding into UCS2 
byte[] bufferToConvert = "Hello World! £€".getBytes(); 
CharBuffer cbuf = decoder.decode(ByteBuffer.wrap(bufferToConvert)); 

// Convert the internal UCS2 representation into outputEncoding 
ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(cbuf)); 
System.out.println(new String(bbuf.array(), 0, bbuf.limit(), charsetOutput)); 

baskılar

Hello World! £€ 
+0

Ancak, giriş kodlamasından bir CharsetDecoder bildirmeniz gerekir. Bir şey gibi: CharsetDecoder decoder = charsetInput.newEncoder() Burada charsetInput = Charset.forName ("cp1252"). – robob

+0

Benzer bir soru var: http://stackoverflow.com/questions/1252468/java-converting-string-to-and-from-bytebuffer-and-associated-problems – robob

+0

Boş dizinin eksik "kod çözücü" olabileceğini düşünüyor musunuz? .flush "ve" encoder.flush "? Ayrıca bkz. Kodunuzda flush() kullanmadıysanız ... – robob

İlgili konular