2015-04-10 4 views
5

Ho un problema con CharsetDecoder di classe.cosa è CharsetDecoder.decode (ByteBuffer, CharBuffer, endOfInput)

primo esempio di codice (che funziona):

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

Il risultato è a€a

Ma quando eseguo questo codice:

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

Il risultato è a

Perché non è lo stesso risultato?

Come utilizzare il metodo decode(ByteBuffer, CharBuffer, endOfInput) della classe CharsetDecoder per recuperare il risultato a€a?

- EDIT -

Quindi, con il codice di Jesper lo faccio. Non è perfetto, ma funziona con un step = 1, 2 e 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

Il risultato è un? Non aa? È molto strano – immibis

+1

La mia uscita per la seconda variante è 'a a' (tre spazi). – Seelenvirtuose

+0

Nel mio caso il risultato è solo "a" con un ritorno a capo – lecogiteur

risposta

1

Il metodo decode(ByteBuffer, CharBuffer, boolean) restituisce un risultato, ma si sta ignorando il risultato. Se stampare il risultato nel frammento di secondo codice:

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

vedrete questa uscita:

UNDERFLOW 
MALFORMED[1] 
MALFORMED[1] 
a a 

A quanto pare non funziona correttamente se si avvia la decodifica nel bel mezzo di un personaggio. Il decodificatore si aspetta che la prima cosa che legge sia l'inizio di una sequenza UTF-8 valida.

modifica - Quando il decoder riporta UNDERFLOW, si aspetta di aggiungere altri dati al buffer di ingresso e quindi provare a chiamare decode() di nuovo, ma è necessario ri-offrirlo i dati dall'inizio del UTF-8 sequenza che stai cercando di decodificare. Non è possibile continuare nel mezzo di una sequenza UTF-8.

Ecco una versione che funziona, l'aggiunta di un byte da tab in ogni iterazione del ciclo:

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

Non hai fornire risposta alla domanda: come ** utilizzare questo metodo ** su ** risultato dell'archivio **. – Andremoniy

+0

@Andremoniy Quindi, stai votando per vendetta, perché ho notato che la tua risposta è sbagliata? – Jesper

+0

L'ho downvoted perché non è una risposta. Se fossi OP - Non capirei come risolvere il mio codice dalla tua risposta – Andremoniy