Java Преобразование из строки в байты не один-один? - PullRequest
1 голос
/ 15 февраля 2012

Я сделал простой тест, и кажется, что Java-преобразование String в байты [] не один-один, по крайней мере, с использованием UTF-8.Код:

    byte[] bytes1 = {-1, 127, 0, 38, 97, 104, 55, 110, 50, -24, -48, 59, -20, -6, 64, 1, 4, 107, 56, 54 };      
    String msg  = new String( bytes1, "UTF-8" );        
    byte[] bytes2 = msg.getBytes( "UTF-8" );                            
    for( byte curr : bytes1 ) {         
        System.out.print( curr );
        System.out.print( ", " );
    }
    System.out.println();
    for( byte curr : bytes2 ) { 
        System.out.print( curr );
        System.out.print( ", " );
    }

Я предполагал, что увижу две равные строки вывода.На самом деле это было:

 -1, 127, 0, 38, 97, 104, 55, 110, 50, -24, -48, 59, -20, -6, 64, 1, 4, 107, 56, 54, 

 -17, -65, -67, 127, 0, 38, 97, 104, 55, 110, 50, -17, -65, -67, -17, -65, -67, 59, -17, -65, -67, -17, -65, -67, 64, 1, 4, 107, 56, 54, 

Интересно, почему это происходит и как я могу добиться конвертации один-один.Кто-нибудь знает?

Ответы [ 2 ]

3 голосов
/ 15 февраля 2012

Вы не можете для произвольного текста. Преобразование из UTF-16 (представление в строке) в UTF-8 определяется как не один-к-одному. См. Стандарт Unicode на Unicode.org.

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

См. http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html. Если вам не нужна спецификация, используйте вариант без опознавательных знаков.

0 голосов
/ 16 февраля 2012

В общем, ответ на мой вопрос - НЕТ. Преобразование из байтов в строку и обратно не является одним, из-за двух фактов:
1. Внутреннее представление String составляет два байта на символ, и во многих кодировках (например, UTF-8) длина кода символа является переменной, поэтому некоторые байты могут быть добавлены в конце, особенно если начальная длина массива байтов является четной. 2. Кодировки могут добавить несколько байтов в качестве префикса для своих конкретных целей. Например, UTF-16 добавляет суффикс из двух байтов, который указывает порядок следования байтов в символах.

Однако мне нужно это преобразование для очень конкретной цели. Я хочу использовать небольшие объекты, используя AmazonSQS, между нашими приложениями. Мы используем сериализатор Kryo, который преобразует объекты в байтовый массив, но сообщения SQS являются строками. Итак, я не использую «настоящие» строки, и мой обходной путь:
1. Если длина строки четная, добавьте три байта: 0,1,1, иначе добавьте два байта: 0,0 к байтовому массиву. 2. Преобразуйте байтовый массив в строку, используя

    message = URLEncoder.encode( new String( bytes, "UTF-16LE" ), "UTF-16LE" );

UTF-16LE, поскольку порядок байтов в символе уже известен и в нем отсутствует префикс в два байта.
3. Отправить сообщение в очередь. 4. Другое приложение читает сообщение из очереди и создает

    byte[] bytes = URLDecoder.decode( message, "UTF-16LE" ).getBytes( "UTF-16LE" );

5. Если последний байт равен 0, используйте все байты, кроме последних двух, для десериализации, иначе используйте все байты, кроме последних трех.

...