web-dev-qa-db-fra.com

Java ByteBuffer à String

Est-ce une bonne approche pour convertir ByteBuffer en String de cette manière,

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

La raison pour laquelle je pose la question est que cela semble trop simple, alors que d’autres approches telles que Java: Convertir une chaîne de ByteBuffer vers et depuis ByteBuffer et les problèmes associés semble plus complexe.

95
vikky.rk

EDIT (2018): La réponse modifiée par @xinyongCheng est une approche plus simple et devrait être la réponse acceptée. _

Votre approche serait raisonnable si vous saviez que les octets sont dans le jeu de caractères par défaut de la plate-forme. Dans votre exemple, cela est vrai car k.getBytes() renvoie les octets dans le jeu de caractères par défaut de la plate-forme.

Plus souvent, vous voudrez spécifier le codage. Cependant, il existe un moyen plus simple de le faire que la question que vous avez liée. L'API String fournit des méthodes qui convertissent entre un tableau String et un tableau byte [] dans un codage particulier. Ces méthodes suggèrent d'utiliser CharsetEncoder/CharsetDecoder "lorsque davantage de contrôle sur le processus de décodage [codage] est requis."

Pour obtenir les octets d'une chaîne dans un codage particulier, vous pouvez utiliser une méthode similaire getBytes ():

byte[] bytes = k.getBytes( StandardCharsets.UTF_8 );

Pour mettre des octets avec un encodage particulier dans une chaîne, vous pouvez utiliser un constructeur différent:

String v = new String( bytes, StandardCharsets.UTF_8 );

Notez que ByteBuffer.array() est une opération facultative. Si vous avez construit votre ByteBuffer avec un tableau, vous pouvez utiliser ce tableau directement. Sinon, si vous voulez être sûr, utilisez ByteBuffer.get(byte[] dst, int offset, int length) pour extraire les octets de la mémoire tampon dans un tableau d'octets.

69
Andy Thomas

Il existe une approche plus simple pour décoder une ByteBuffer en une String sans aucun problème, mentionnée par Andy Thomas. 

String s = StandardCharsets.UTF_8.decode(byteBuffer).toString();
54
xinyong Cheng

Essaye ça:

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

NB vous ne pouvez pas convertir correctement un tableau d'octets en chaîne sans connaître son encodage.

J'espère que ça aide

16
Dan Bray

Je voulais juste souligner, il n’est pas prudent de supposer que ByteBuffer.array () fonctionnera toujours.

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

En général, buffer.hasArray () sera toujours vrai ou faux en fonction de votre cas d'utilisation. En pratique, à moins que vous ne vouliez vraiment que cela fonctionne, il est prudent d'optimiser la succursale dont vous n'avez pas besoin. Mais le reste des réponses peut ne pas fonctionner avec un ByteBuffer créé via ByteBuffer.allocateDirect ().

11
Fuwjax

Les réponses concernant simplement l'appel de array() ne sont pas tout à fait correctes: lorsque le tampon a été partiellement utilisé ou se réfère à une partie d'un tableau (vous pouvez ByteBuffer.wrap un tableau à un offset donné, pas nécessairement du début en tenir compte dans nos calculs. C'est la solution générale qui fonctionne pour les tampons dans tous les cas (ne couvre pas le codage):

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

Pour les problèmes liés au codage, voir la réponse de Andy Thomas.

4
Alex Yarmula

Convertit une chaîne en ByteBuffer, puis de ByteBuffer en chaîne en utilisant 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();
}

Ce qui affiche la chaîne nue imprimée en premier, puis le ByteBuffer converti en array ():

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

Cela m'a aussi été utile, réduire la chaîne en octets primitifs peut aider à inspecter ce qui se passe:

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

Imprime votre chaîne interprétée au format UTF-8, puis à nouveau au format ISO-8859-1:

こんにちは
ããã«ã¡ã¯
1
Eric Leschinski

Notez (à part le problème de codage) que certains des codes les plus complexes liés ont du mal à obtenir la partie "active" du ByteBuffer en question (par exemple en utilisant position et limit), plutôt que de simplement coder tous les octets dans l’ensemble du tableau de fond (comme le font bon nombre des exemples de ces réponses).

1
Jas

la racine de cette question est comment décoder des octets en chaîne?

cela peut être fait avec le Java NIO CharSet:

public final CharBuffer decode(ByteBuffer bb)

 enter image description here

0
宏杰李
private String convertFrom(String lines, String from, String to) {
    ByteBuffer bb = ByteBuffer.wrap(lines.getBytes());
    CharBuffer cb = Charset.forName(to).decode(bb);
    return new String(Charset.forName(from).encode(cb).array());
};
public Doit(){
    String concatenatedLines = convertFrom(concatenatedLines, "CP1252", "UTF-8");
};
0
Koenraad Appelo