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.
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 .
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". String
s 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.
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:
String.toByteArray
avec un jeu de caractères explicite.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)
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.
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();
}
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);
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;
}
javax.xml.bind.DatatypeConverter
devrait le faire:
byte [] b = javax.xml.bind.DatatypeConverter.parseHexBinary("E62DB");
String s = javax.xml.bind.DatatypeConverter.printHexBinary(b);
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();
}
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.
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();
}
É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.
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);
}