web-dev-qa-db-fra.com

Comment convertir un tableau d'octets en chaîne et vice versa?

Je dois convertir un tableau d'octets en chaîne dans Android, mais mon tableau d'octets contient des valeurs négatives.

Si je convertis à nouveau cette chaîne en tableau d'octets, les valeurs que je récupère sont différentes des valeurs d'origine du tableau d'octets.

Que puis-je faire pour obtenir une conversion correcte? Le code que j'utilise pour effectuer la conversion est le suivant:

// Code to convert byte arr to str:
byte[] by_original = {0,1,-2,3,-4,-5,6};
String str1 = new String(by_original);
System.out.println("str1 >> "+str1);

// Code to convert str to byte arr:
byte[] by_new = str1.getBytes();
for(int i=0;i<by_new.length;i++) 
System.out.println("by1["+i+"] >> "+str1);

Je suis coincé dans ce problème.

193
Jyotsna

Votre tableau d'octets doit avoir un certain encodage. Le codage ne peut pas être ASCII si vous avez des valeurs négatives. Une fois que vous avez compris cela, vous pouvez convertir un ensemble d'octets en chaîne en utilisant:

byte[] bytes = {...}
String str = new String(bytes, "UTF-8"); // for UTF-8 encoding

Vous pouvez utiliser un grand nombre d'encodages. Regardez la classe Charset dans le fichier Sun javadocs .

305
omerkudat

La "conversion correcte" entre byte[] et String consiste à indiquer explicitement le codage que vous souhaitez utiliser. Si vous commencez par un byte[] et que celui-ci ne contient pas de données textuelles, il y a est non "conversion correcte". Strings sont pour du texte, byte[] est pour des données binaires, et la seule chose vraiment judicieuse à faire est de convertir éviter entre eux, sauf obligation absolue.

Si vous devez réellement utiliser une variable String pour stocker des données binaires, le moyen le plus sûr consiste à utiliser Base64 encoding.

97

Le problème fondamental est (je pense) que vous utilisez involontairement un jeu de caractères pour lequel:

 bytes != encode(decode(bytes))

dans certains cas. UTF-8 est un exemple d'un tel jeu de caractères. Plus précisément, certaines séquences d'octets ne sont pas des codages valides en UTF-8. Si le décodeur UTF-8 rencontre l'une de ces séquences, il est susceptible de supprimer les octets incriminés ou de les décoder en tant que point de code Unicode pour "aucun caractère de ce type". Naturellement, lorsque vous essayez ensuite de coder les caractères sous forme d'octets, le résultat sera différent.

La solution est:

  1. Soyez explicite sur le codage de caractères que vous utilisez; c'est-à-dire utiliser un constructeur String et une méthode String.toByteArray avec un jeu de caractères explicite.
  2. Utilisez le bon jeu de caractères pour vos données d'octet ... ou bien un autre (tel que "Latin-1" où toutes les séquences d'octets sont mappées sur des caractères Unicode valides.
  3. Si vos octets sont (vraiment) des données binaires et que vous voulez pouvoir les transmettre/recevoir sur un canal "basé sur du texte", utilisez quelque chose comme l'encodage Base64 ... conçu à cet effet .
36
Stephen C

Nous avons juste besoin de construire une nouvelle variable String avec le tableau: http://www.mkyong.com/Java/how-do-convert-byte-array-to-string-in-Java/

String s = new String(bytes);

Les octets de la chaîne résultante varient en fonction du jeu de caractères que vous utilisez. new String (octets) et new String (octets, Charset.forName ("utf-8")) et new String (octets, Charset.forName ("utf-16")) auront tous des tableaux d'octets différents lorsque vous appelez String #. getBytes () (en fonction du jeu de caractères par défaut) 

29
Ravindranath Akila

Utiliser new String(byOriginal) et reconvertir en byte[] en utilisant getBytes() ne garantit pas deux byte[] avec des valeurs égales. Cela est dû à un appel àStringCoding.encode(..)qui va coder String enCharset.defaultCharset(). Pendant ce codage, le codeur peut choisir de remplacer des caractères inconnus et d’apporter d’autres modifications. Par conséquent, l'utilisation de String.getBytes() pourrait ne pas renvoyer un tableau identique à celui que vous avez initialement transmis au constructeur.

12
sfussenegger

Pourquoi le problème était-il: Comme quelqu'un l'a déjà précisé: Si vous commencez par un octet [] et qu'il ne contient pas de données texte, il n'y a pas de "conversion correcte". Les chaînes sont pour le texte, byte [] est pour les données binaires, et la seule chose sensée à faire est d'éviter de convertir entre eux sauf si vous devez absolument.} _

J'observais ce problème lorsque je tentais de créer byte [] à partir d'un fichier pdf, puis de le convertir en chaîne, puis de prendre la chaîne en tant qu'entrée et de la reconvertir en fichier.  

Assurez-vous donc que votre logique d’encodage et de décodage est la même que celle que j’ai faite. J'ai explicitement encodé l'octet [] en Base64 et l'ai décodé pour créer le fichier à nouveau.

Cas d'utilisation: En raison de certaines limitations, j'essayais d'envoyer byte[] dans request(POST) et le processus était le suivant:

PDF Fichier >> Base64.encodeBase64 (octet []) >> Chaîne >> Demande d'envoi (POST) >> receive Chaîne >> Base64.decodeBase64 (octet []) >> créer un fichier binaire

Essayez ceci et cela a fonctionné pour moi ..

File file = new File("filePath");

        byte[] byteArray = new byte[(int) file.length()];

        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            fileInputStream.read(byteArray);

            String byteArrayStr= new String(Base64.encodeBase64(byteArray));

            FileOutputStream fos = new FileOutputStream("newFilePath");
            fos.write(Base64.decodeBase64(byteArrayStr.getBytes()));
            fos.close();
        } 
        catch (FileNotFoundException e) {
            System.out.println("File Not Found.");
            e.printStackTrace();
        }
        catch (IOException e1) {
            System.out.println("Error Reading The File.");
            e1.printStackTrace();
        }
9
Rupesh

Cela fonctionne bien pour moi:

String cd="Holding some value";

Conversion de chaîne en octet []:

byte[] cookie = new Sun.misc.BASE64Decoder().decodeBuffer(cd);

Conversion d'octet [] en chaîne:

cd = new Sun.misc.BASE64Encoder().encode(cookie);
6
LeD
private static String toHexadecimal(byte[] digest){
        String hash = "";
    for(byte aux : digest) {
        int b = aux & 0xff;
        if (Integer.toHexString(b).length() == 1) hash += "0";
        hash += Integer.toHexString(b);
    }
    return hash;
}
5
sdelvalle57

javax.xml.bind.DatatypeConverter devrait le faire:

byte [] b = javax.xml.bind.DatatypeConverter.parseHexBinary("E62DB");
String s = javax.xml.bind.DatatypeConverter.printHexBinary(b);
2
Wolfgang Kaisers

Voici quelques méthodes qui convertissent un tableau d'octets en chaîne. Je les ai testés ils fonctionnent bien.

public String getStringFromByteArray(byte[] settingsData) {

    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(settingsData);
    Reader reader = new BufferedReader(new InputStreamReader(byteArrayInputStream));
    StringBuilder sb = new StringBuilder();
    int byteChar;

    try {
        while((byteChar = reader.read()) != -1) {
            sb.append((char) byteChar);
        }
    }
    catch(IOException e) {
        e.printStackTrace();
    }

    return sb.toString();

}

public String getStringFromByteArray(byte[] settingsData) {

    StringBuilder sb = new StringBuilder();
    for(byte willBeChar: settingsData) {
        sb.append((char) willBeChar);
    }

    return sb.toString();

}
2
user2288580

Bien que l'encodage en base64 soit sûr et que l'on puisse dire "la bonne réponse", je suis arrivé ici en cherchant un moyen de convertir un tableau d'octets Java en/à partir d'une chaîne Java en l'état. C'est-à-dire que chaque membre du tableau d'octets reste intact dans sa contrepartie String, sans espace supplémentaire requis pour le codage/transport.

Cette réponse décrivant les codages transparents à 8 bits m'a été très utile. J'ai utilisé ISO-8859-1 sur des téraoctets de données binaires pour effectuer une conversion (binary <-> String) avec succès sans les besoins en espace non nécessaire pour un codage en base64;.

Cela a également été utile pour expliquer quand/si vous devriez expérimenter.

1
Reed Sandberg

J'ai réussi à convertir un tableau d'octets en chaîne avec cette méthode:

public static String byteArrayToString(byte[] data){
    String response = Arrays.toString(data);

    String[] byteValues = response.substring(1, response.length() - 1).split(",");
    byte[] bytes = new byte[byteValues.length];

    for (int i=0, len=bytes.length; i<len; i++) {
        bytes[i] = Byte.parseByte(byteValues[i].trim());
    }

    String str = new String(bytes);
    return str.toLowerCase();
}
1
lxknvlk

Événement si 

new String(bytes, "UTF-8")

est correct, il jette une UnsupportedEncodingException qui vous oblige à traiter une exception vérifiée. Vous pouvez utiliser alternativement un autre constructeur depuis Java 1.6 pour convertir un tableau d'octets en un String:

new String(bytes, StandardCharsets.UTF_8)

Celui-ci ne jette aucune exception.

La conversion doit également être effectuée avec StandardCharsets.UTF_8:

"test".getBytes(StandardCharsets.UTF_8)

Encore une fois, vous évitez d'avoir à traiter avec des exceptions vérifiées.

0
gil.fernandes
import Sun.misc.BASE64Decoder;
import Sun.misc.BASE64Encoder;    

private static String base64Encode(byte[] bytes)
{
    return new BASE64Encoder().encode(bytes);
}

private static byte[] base64Decode(String s) throws IOException
{
    return new BASE64Decoder().decodeBuffer(s);
}
0
Feng Zhang