2015-04-10 7 views
5

Mam problem z klasą CharsetDecoder.Co to jest CharsetDecoder.decode (ByteBuffer, CharBuffer, endOfInput)

Pierwszy przykład kodu (które działa):

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

Rezultatem jest a€a

Ale kiedy wykonać ten kod:

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

wynik jest a

Dlaczego nie są takie same wyniki?

Jak użyć metody decode(ByteBuffer, CharBuffer, endOfInput) klasy CharsetDecoder w celu pobrania wyniku a€a?

- EDIT -

Więc z kodeksem Jesper to zrobić. To nie jest idealne, ale współpracuje z step = 1, 2 i 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

Rezultatem jest? Nie aa? To bardzo dziwne. – immibis

+1

Moje dane wyjściowe dla drugiego wariantu to "a" (trzy spacje). – Seelenvirtuose

+0

W moim przypadku wynik jest tylko "a" z powrotem karetki – lecogiteur

Odpowiedz

1

Metoda decode(ByteBuffer, CharBuffer, boolean) zwraca wynik, ale ignorują wynik. Jeśli wydrukować wynik w drugim fragmencie kodu:

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

zobaczysz wynik:

UNDERFLOW 
MALFORMED[1] 
MALFORMED[1] 
a a 

Najwyraźniej nie działa prawidłowo, jeśli rozpocząć dekodowanie w środku znaku. Dekoder oczekuje, że pierwszą rzeczą, którą odczyta, jest początek prawidłowej sekwencji UTF-8.

edit - Kiedy zgłasza dekoder UNDERFLOW, że spodziewa się dodać więcej danych do bufora wejściowego, a następnie spróbuj zadzwonić decode() ponownie, ale trzeba ponownie zaoferować go dane z początku UTF-8 sekwencję, którą próbujesz rozszyfrować. Nie możesz kontynuować w trakcie sekwencji UTF-8.

Oto wersja, która działa, dodając jeden bajt z tab w każdej iteracji pętli:

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

Nie dostarczyłeś odpowiedzi na pytanie: ** jak użyj tej metody **, aby ** zarchiwizować wynik **. – Andremoniy

+0

@Andremoniy Więc, głosujesz to zemstą, ponieważ zauważyłem, że twoja odpowiedź jest zła? – Jesper

+0

Zignorowałem to, ponieważ nie jest to odpowiedź. Gdybym był OP - nie rozumiem, jak naprawić mój kod od ciebie odpowiedź – Andremoniy