Преобразование из Windows 1252 в UTF8 в Java: нулевые символы с помощью CharsetDecoder / Encoder - PullRequest
11 голосов
/ 25 мая 2011

Я знаю, что это очень общий вопрос, но я схожу с ума.

Я использовал этот код:

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

Но я читал, что лучше использовать CharsetDecoder и CharsetEncoder (у меня есть содержимое с некоторым символом, вероятно, за пределами кодировки назначения). Я только что написал этот код, но у него есть некоторые проблемы:

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

Действительно, этот код добавляет в буфер последовательность нулевых символов !!!!!

Может кто-нибудь сказать мне, в чем проблема? Я не очень опытен с преобразованием кодировки в Java.

Есть ли лучший способ конвертировать кодировку в Java?

Ответы [ 2 ]

7 голосов
/ 26 мая 2011

Ваша проблема в том, что ByteBuffer.array() возвращает прямую ссылку на массив, используемый в качестве резервного хранилища для ByteBuffer, а не копию действительного диапазона резервного массива.Вы должны подчиняться bbuf.limit() (как это делал Питер в своем ответе) и просто использовать содержимое массива от индекса 0 до bbuf.limit()-1.

. Причина дополнительных 0 значений в массиве поддержки состоит вНебольшой недостаток в том, как результирующий ByteBuffer создается CharsetEncoder.Каждый кодировщик CharsetEncoder имеет «среднее число байтов на символ», которое для кодера UCS2 кажется простым и правильным (2 байта на символ).Подчиняясь этому фиксированному значению, CharsetEncoder первоначально выделяет ByteBuffer с байтами «длина строки * среднее число байт на символ», в этом случае, например, 20 байтов для строки длиной 10 символов.Однако кодирование UCS2 CharsetEncoder начинается с спецификации (метки порядка байтов), которая также занимает 2 байта, так что только 9 из 10 символов помещаются в выделенный ByteBuffer.CharsetEncoder обнаруживает переполнение и выделяет новый ByteBuffer длиной 2 * n + 1 (n является исходной длиной ByteBuffer), в этом случае 2 * 20 + 1 = 41 байт.Поскольку для кодирования оставшегося символа требуются только 2 из 21 нового байта, массив, полученный из bbuf.array(), будет иметь длину 41 байт, но bbuf.limit() будет указывать, что фактически используются только первые 22 записи.

4 голосов
/ 25 мая 2011

Я не уверен, как вы получаете последовательность null символов.Попробуйте это

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

печать

Hello World! £€
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...