2013-06-27 14 views
78

È questo un approccio corretto per convertire ByteBuffer a stringa in questo modo,Java ByteBuffer a String

String k = "abcd"; 
ByteBuffer b = ByteBuffer.wrap(k.getBytes()); 
String v = new String(b.array()); 

if(k.equals(v)) 
    System.out.println("it worked"); 
else 
    System.out.println("did not work"); 

Il motivo che mi chiedo è che è questo sembra troppo semplice, mentre altri approcci come Java: Converting String to and from ByteBuffer and associated problems sembra più complessa.

+2

Bene, ci hai provato? – Doorknob

+5

Sì, l'ho fatto e funziona. Ma ho visto altre implementazioni più complesse, come http://stackoverflow.com/questions/1252468/java-conversing-string-to-and-from-bytebuffer-and-associato-problemi –

+1

@Doorknob et. al. Manca la codifica e il suo esempio (quando la sintassi è corretta) funzionerà, ma il suo metodo non è ancora corretto. – Gus

risposta

58

Il tuo approccio sarebbe ragionevole se si sapeva i byte sono in charset di default della piattaforma. Nel tuo esempio, questo è vero perché k.getBytes() restituisce i byte nel set di caratteri predefinito della piattaforma.

Più frequentemente, ti consigliamo di specificare la codifica. Tuttavia, c'è un modo più semplice per farlo rispetto alla domanda che hai collegato. L'API String fornisce metodi che converte tra una stringa e una matrice byte [] in una particolare codifica. Questi metodi suggeriscono di usare CharsetEncoder/CharsetDecoder "quando è richiesto un maggiore controllo sul processo di decodifica [codifica]."

import java.nio.charset.Charset; 

Per ottenere i byte da una stringa in una codifica particolare, è possibile utilizzare un fratello getBytes() metodo:

byte[] bytes = k.getBytes(Charset.forName("UTF-8")); 

Per mettere byte con una codifica particolare in una stringa, si può utilizzare un costruttore String diversa:

String v = new String(bytes, Charset.forName("UTF-8")); 

noti che ByteBuffer.array() è un'operazione facoltativa. Se hai costruito ByteBuffer con un array, puoi utilizzare direttamente tale array. In caso contrario, se si desidera essere sicuri, utilizzare ByteBuffer.get(byte[] dst, int offset, int length) per ottenere byte dal buffer in un array di byte.

EDIT

Come una questione secondaria, nel codice di esempio sopra la chiamata a Charset.forName("UTF-8") dovrebbe funzionare per tutte le versioni di Java, in quanto 1.4.

Se si utilizza Java 7 o successivo, è invece possibile utilizzare java.nio.charset.StandardCharsets.UTF_8. (notato da BenKirby nel suo commento qui sotto.)

Se stai usando Guava, è possibile invece utilizzare com.google.common.base.Charsets.UTF_8. (annotato da Spacecamel nel suo commento qui sotto)

+0

e nella funzione 'ByteBuffer.get', l'input è di nuovo una matrice di byte, come posso ottenerlo? non ha senso dire di nuovo k.getbytes, vero? –

+0

@WilliamKinaan - Hai il byte [] che hai fornito a 'ByteBuffer.get (byte [] dst, int offset, int length)'. È possibile creare una stringa al di fuori di essa con il costruttore String 'String() (byte [] byte, int offset, lunghezza int, set di caratteri Charset). È possibile utilizzare gli stessi valori di offset e lunghezza per entrambe le chiamate. –

+0

Non c'è alcun metodo k.getBytes() in java.nio.ByteBuffer (potrebbe non essere nella versione che sto utilizzando). Quindi ho usato il metodo k.array() che restituirà il byte []. –

13

Prova questa:

new String(bytebuffer.array(), "ASCII"); 

NB. non è possibile convertire correttamente una matrice di byte in una stringa senza conoscerne la codifica.

Spero che questo aiuta

+9

UTF-8 è probabilmente un'ipotesi predefinita migliore di ASCII? – Gus

+3

Nessuno dei due deve essere specificato, dato l'uso dell'OP di k.getBytes(), che utilizza il set di caratteri predefinito della piattaforma. –

+5

Non tutti i buffer sono supportati da un array, quindi '.array()' può generare un'eccezione. –

12

Volevo solo precisare, non è sicuro assumere ByteBuffer.array() funzionerà sempre.

byte[] bytes; 
if(buffer.hasArray()) { 
    bytes = buffer.array(); 
} else { 
    bytes = new byte[buffer.remaining()]; 
    buffer.get(bytes); 
} 
String v = new String(bytes, charset); 

Di solito buffer.hasArray() sarà sempre true o false a seconda del caso d'uso. In pratica, a meno che tu non voglia che funzioni in qualsiasi circostanza, è sicuro ottimizzare il ramo che non ti serve. Ma il resto delle risposte potrebbe non funzionare con un ByteBuffer che è stato creato tramite ByteBuffer.allocateDirect().

+0

Se il buffer viene creato tramite 'ByteBuffer.wrap (bytes, offset, size) 'factory' .array() 'restituirà l'intera matrice' bytes'. Meglio usare il modulo xinyong Cheng suggerito –

+0

Il .decode() su Charset è una soluzione migliore, d'accordo. Sento che il contesto della mia risposta è un'informazione utile, ma molto meno adesso. – Fuwjax

0

Avviso (a parte il problema di codifica) che alcuni dei più complicati codici collegati vanno alla difficoltà di ottenere la parte "attiva" del ByteBuffer in questione (ad esempio usando posizione e limite), piuttosto che semplicemente la codifica tutti i byte nell'intero backing array (come fanno molti esempi in queste risposte).

3

Le risposte che si riferiscono alla semplice chiamata array() non sono del tutto corrette: quando il buffer è stato parzialmente consumato o si riferisce a una parte di un array (è possibile ByteBuffer.wrap un array a un dato offset, non necessariamente dall'inizio) , dobbiamo tenerne conto nei nostri calcoli. Questa è la soluzione generale che funziona per i buffer in tutti i casi (non copre la codifica):

if (myByteBuffer.hasArray()) { 
    return new String(myByteBuffer.array(), 
     myByteBuffer.arrayOffset() + myByteBuffer.position(), 
     myByteBuffer.remaining()); 
} else { 
    final byte[] b = new byte[myByteBuffer.remaining()]; 
    myByteBuffer.duplicate().get(b); 
    return new String(b); 
} 

Per le preoccupazioni relative alla codifica, vedi risposta Andy Thomas'.

1

Convertire una stringa in ByteBuffer, poi da ByteBuffer torna a String utilizzando Java:

import java.nio.charset.Charset; 
import java.nio.*; 

String babel = "obufscate thdé alphebat and yolo!!"; 
System.out.println(babel); 
//Convert string to ByteBuffer: 
ByteBuffer babb = Charset.forName("UTF-8").encode(babel); 
try{ 
    //Convert ByteBuffer to String 
    System.out.println(new String(babb.array(), "UTF-8")); 
} 
catch(Exception e){ 
    e.printStackTrace(); 
} 

che consente di stampare la stringa nuda stampata prima, e poi la ByteBuffer colato a array():

obufscate thdé alphebat and yolo!! 
obufscate thdé alphebat and yolo!! 

anche questo è stato utile per me, riducendo la stringa di byte primitivi può aiutare a controllare cosa sta succedendo:

String text = "こんにちは"; 
//convert utf8 text to a byte array 
byte[] array = text.getBytes("UTF-8"); 
//convert the byte array back to a string as UTF-8 
String s = new String(array, Charset.forName("UTF-8")); 
System.out.println(s); 
//forcing strings encoded as UTF-8 as an incorrect encoding like 
//say ISO-8859-1 causes strange and undefined behavior 
String sISO = new String(array, Charset.forName("ISO-8859-1")); 
System.out.println(sISO); 

di stampare la stringa interpretata come UTF-8, e poi di nuovo come ISO-8859-1:

こんにちは 
ããã«ã¡ã¯ 
31

C'è approccio più semplice per decodificare un ByteBuffer in una String senza problemi, menzionati da Andy Thomas.

String s = StandardCharsets.UTF_8.decode(byteBuffer).toString(); 
+1

Si noti che UTF-8 potrebbe non essere il set di caratteri ottimale per convertire i byte in stringhe e viceversa. Per una mappatura 1-a-1 dei byte ai caratteri, utilizzare meglio ISO-8859-1, vedere https://stackoverflow.com/questions/9098022/problems-converting-byte-array-to-string-and-back-to -byte-array. – asmaier