2015-04-10 4 views
5

У меня проблема с классом CharsetDecoder.Что такое CharsetDecoder.decode (ByteBuffer, CharBuffer, endOfInput)

Первый пример кода (который работает):

final CharsetDecoder dec = Charset.forName("UTF-8").newDecoder(); 
    final ByteBuffer b = ByteBuffer.allocate(3); 
    final byte[] tab = new byte[]{(byte)-30, (byte)-126, (byte)-84}; //char € 
    for (int i=0; i<tab.length; i++){ 
     b.put(tab, i, 1); 
    } 
    try { 
     b.flip(); 
     System.out.println("a" + dec.decode(b).toString() + "a"); 
    } catch (CharacterCodingException e1) { 
     e1.printStackTrace(); 
    } 

В результате a€a

Но когда я исполняю этот код:

final CharsetDecoder dec = Charset.forName("UTF-8").newDecoder(); 
    final CharBuffer chars = CharBuffer.allocate(3); 
    final byte[] tab = new byte[]{(byte)-30, (byte)-126, (byte)-84}; //char € 
    for (int i=0; i<tab.length; i++){ 
     ByteBuffer buffer = ByteBuffer.wrap(tab, i, 1); 
     dec.decode(buffer, chars, i == 2); 
    } 
    dec.flush(chars); 
    System.out.println("a" + chars.toString() + "a"); 

Результат является a

Почему не такой же результат?

Как использовать метод decode(ByteBuffer, CharBuffer, endOfInput) класса CharsetDecoder для того, чтобы восстановить результат a€a?

- EDIT -

Так с кодом Jesper я могу это сделать. Это не идеально, но работает с step = 1, 2 и 3

final CharsetDecoder dec = Charset.forName("UTF-8").newDecoder(); 
    final CharBuffer chars = CharBuffer.allocate(6); 
    final byte[] tab = new byte[]{(byte)97, (byte)-30, (byte)-126, (byte)-84, (byte)97, (byte)97}; //char € 

    final ByteBuffer buffer = ByteBuffer.allocate(10); 

    final int step = 3; 
    for (int i = 0; i < tab.length; i++) { 
     // Add the next byte to the buffer 
     buffer.put(tab, i, step); 
     i+=step-1; 

     // Remember the current position 
     final int pos = buffer.position(); 
     int l=chars.position(); 

     // Try to decode 
     buffer.flip(); 
     final CoderResult result = dec.decode(buffer, chars, i >= tab.length -1); 
     System.out.println(result); 

     if (result.isUnderflow() && chars.position() == l) { 
      // Underflow, prepare the buffer for more writing 
      buffer.position(pos); 
     }else{ 
      if (buffer.position() == buffer.limit()){ 
       //ByteBuffer decoded 
       buffer.clear(); 
       buffer.position(0); 
      }else{ 
       //a part of ByteBuffer is decoded. We keep only bytes which are not decoded 
       final byte[] b = buffer.array(); 
       final int f = buffer.position(); 
       final int g = buffer.limit() - buffer.position(); 
       buffer.clear(); 
       buffer.position(0); 
       buffer.put(b, f, g); 
      } 
     } 
     buffer.limit(buffer.capacity()); 
    } 

    dec.flush(chars); 
    chars.flip(); 

    System.out.println(chars.toString()); 
+1

В результате? Не а? Это очень странно. – immibis

+1

Мой вывод для второго варианта - 'a a' (три пробела). – Seelenvirtuose

+0

В моем случае результатом является только «a» с возвратом каретки. – lecogiteur

ответ

1

Метод decode(ByteBuffer, CharBuffer, boolean) возвращает результат, но вы не обращая внимания на результат. Если распечатать результат в вашем втором фрагменте кода:

for (int i = 0; i < tab.length; i++) { 
    ByteBuffer buffer = ByteBuffer.wrap(tab, i, 1); 
    System.out.println(dec.decode(buffer, chars, i == 2)); 
} 

вы увидите этот вывод:

UNDERFLOW 
MALFORMED[1] 
MALFORMED[1] 
a a 

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

редактировать - Когда декодер сообщает UNDERFLOW, он ожидает, что вы добавить больше данных в буфер ввода, а затем попытаться вызвать decode() снова, но вы должны повторно предложить его данные с самого начала из UTF-8 последовательность, которую вы пытаетесь декодировать. Вы не можете продолжать посередине последовательности UTF-8.

Вот версия, которая работает, добавляя один байт из tab в каждой итерации цикла:

final CharsetDecoder dec = Charset.forName("UTF-8").newDecoder(); 
final CharBuffer chars = CharBuffer.allocate(3); 
final byte[] tab = new byte[]{(byte) -30, (byte) -126, (byte) -84}; //char € 

final ByteBuffer buffer = ByteBuffer.allocate(10); 

for (int i = 0; i < tab.length; i++) { 
    // Add the next byte to the buffer 
    buffer.put(tab[i]); 

    // Remember the current position 
    final int pos = buffer.position(); 

    // Try to decode 
    buffer.flip(); 
    final CoderResult result = dec.decode(buffer, chars, i == 2); 
    System.out.println(result); 

    if (result.isUnderflow()) { 
     // Underflow, prepare the buffer for more writing 
     buffer.limit(buffer.capacity()); 
     buffer.position(pos); 
    } 
} 

dec.flush(chars); 
chars.flip(); 

System.out.println("a" + chars.toString() + "a"); 
+0

Вы не ответили на вопрос: ** how используйте этот метод ** для ** результата архива **. – Andremoniy

+0

@Andremoniy Итак, вы голосуете за него из мести, потому что я заметил, что ваш ответ неправильный? – Jesper

+0

Я проигнорировал это, потому что это не ответ. Если бы я был OP - я бы не понял, как исправить мой код от вас ответ – Andremoniy

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