2013-11-25 3 views
1

У меня есть код, который преобразуется из массива char в массив байтов (без создания каких-либо промежуточных строк и это требование), и я получаю некоторые дополнительные байты в конце. Вот некоторые тестового кода, который иллюстрирует эту проблему:Java - преобразованный массив массивов в байтовый массив - длина не соответствует

String s = "TomJSawyer"; 

System.out.println("Original String length = " + s.length()); 

char[] caOrig = s.toCharArray(); 

System.out.println("Original Char Array Length = " + caOrig.length); 

byte[] ba1 = Charset.forName("UTF-8").encode(CharBuffer.wrap(caOrig)).array(); 

System.out.println("byte array converted from char array length = " + ba1.length); 

byte[] ba2 = s.toString().getBytes("UTF-8"); 

System.out.println("byte array converted from String length = " + ba2.length); 

А вот выход работает на jdk160_24 на Winodows.

Original String length = 10 
Original Char Array Length = 10 
byte array converted from char array length = 11 
byte array converted from String length = 10 

Дополнительный байт, который является результатом преобразования из массива символов с использованием Charset, равен нулю. По мере увеличения длины ввода число нулевых байтов, добавленных в конец массива байтов, увеличивается. Я ожидаю, что это имеет какое-то отношение к кодированию, но похоже, что я указываю UTF-8 в обоих местах, поэтому я не знаю, почему это было бы.

Если бы кто-нибудь мог объяснить мне, что происходит, или иначе указать мне в правильном направлении, я бы очень признателен. Заранее спасибо.

ответ

0

Если вы не должны использовать char[], вы можете использовать StringBuffer:

StringBuffer sb = "TomJSawyer"; 

String.valueOf(sb).getBytes(); 
+0

StringBuffer sb = "TomJSawyer"; – MoMan

+2

Спасибо за мысль. К сожалению, String.valueOf() создает промежуточную строку, чего я пытаюсь избежать. – user2801442

5

documentation for CharsetEncoder.encode говорит:

Возвращает: вновь распределённая байт буфер, содержащий результат операции кодирования. Позиция буфера будет равна нулю, и ее предел будет следовать за последним байтом.

Вы ошибочно предположили, что весь массив поддержки ByteBuffer был действительным. Вы должны смотреть только на байты до limit ByteBuffer. Фактически, метод CharsetEncoder.encode не гарантирует, что возвращенный ByteBuffer будет даже поддерживаться массивом, поэтому вы не должны вообще звонить array().

Надежный способ читать ByteBuffer будет:

ByteBuffer buffer = Charset.forName("UTF-8").encode(CharBuffer.wrap(caOrig)); 
byte[] ba1 = new byte[buffer.limit()]; 
buffer.get(ba1); 
+0

Спасибо VGR. Это ответ. Я очень ценю это. – user2801442

+0

Я новичок на сайте. Есть ли способ отметить этот вопрос? – user2801442

+0

Из http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work: «Чтобы отметить ответ как принятый, нажмите галочку рядом с ответом, чтобы переключить его с полого на зеленый (см. снимок экрана ниже) " – VGR

0

Char размер массива отличается от размера массива байтов во многих сценариях. Они не совпадают, когда я использую китайские или японские символы в массиве символов. Я просто исправил ошибку в своем приложении, которая связана с этим.

Вот тест фрагмент кода с использованием китайского иероглифа:

public static void main(String[] args) throws Exception { 
    char[] chars = new char[] { '中', '国' }; 
    System.out.println("string content: " + new String(chars)); 
    System.out.println("char array size: " + chars.length); 
    byte[] bytes = new String(chars).getBytes("UTF-8"); 
    System.out.println("byte array size: " + bytes.length); 
    System.out.println("converted string content: " + new String(bytes, "UTF-8")); 
} 

Вот выход из консоли:

string content: 中国 
char array size: 2 
byte array size: 6 
converted string content: 中国 

Не делайте ту же ошибку, как я сделал.

Смежные вопросы