web-dev-qa-db-fra.com

Conversion de tableau d'octets en chaîne (Java)

J'écris une application Web dans Google app Engine. Il permet aux utilisateurs de modifier le code HTML stocké en tant que fichier .html dans le blobstore.

J'utilise fetchData pour renvoyer un byte[] de tous les caractères du fichier. J'essaye d'imprimer en HTML pour que l'utilisateur puisse éditer le code HTML. Tout fonctionne très bien!

Voici mon seul problème maintenant:

Le tableau d'octets rencontre des problèmes lors de la reconversion en chaîne. Des citations intelligentes et un couple de personnages sont en train de paraître géniaux. (? ou ou symboles japonais, etc.) Plus précisément, je vois plusieurs octets dont les valeurs négatives sont à l'origine du problème.

Les guillemets intelligents reviennent sous la forme -108 et -109 dans le tableau d'octets. Pourquoi est-ce et comment puis-je décoder les octets négatifs pour afficher le codage de caractères correct?

85
Josh

Le tableau d'octets contient des caractères dans un encodage spécial (à savoir). Le moyen de le convertir en chaîne est:

String decoded = new String(bytes, "UTF-8");  // example for one encoding type

À propos - les octets bruts apparaissant peuvent apparaître en décimales négatives simplement parce que le type de données Java byte est signé, il couvre la plage comprise entre -128 et 127.


-109 = 0x93: Control Code "Set Transmit State"

La valeur (-109) est un caractère de contrôle non imprimable dans UNICODE. Donc, UTF-8 n’est pas l’encodage correct pour ce flux de caractères.

0x93 dans "Windows-1252" est la "citation intelligente" que vous recherchez. Le nom Java de cet encodage est "Cp1252". La ligne suivante fournit un code de test:

System.out.println(new String(new byte[]{-109}, "Cp1252")); 
141
Andreas_D

Java 7 et supérieur

Vous pouvez également transmettre le codage souhaité au constructeur String sous la forme d'une constante Charset de StandardCharsets . Cela peut être plus sûr que de passer le codage en tant que String, comme suggéré dans les autres réponses.

Par exemple, pour le codage UTF-8

String bytesAsString = new String(bytes, StandardCharsets.UTF_8);
25
davnicwil

Vous pouvez essayer ça.

String s = new String(bytearray);
11
Muhammad Aamir Ali
public class Main {

    /**
     * Example method for converting a byte to a String.
     */
    public void convertByteToString() {

        byte b = 65;

        //Using the static toString method of the Byte class
        System.out.println(Byte.toString(b));

        //Using simple concatenation with an empty String
        System.out.println(b + "");

        //Creating a byte array and passing it to the String constructor
        System.out.println(new String(new byte[] {b}));

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new Main().convertByteToString();
    }
}

Sortie

65
65
A
5
Adi Sembiring
public static String readFile(String fn)   throws IOException 
{
    File f = new File(fn);

    byte[] buffer = new byte[(int)f.length()];
    FileInputStream is = new FileInputStream(fn);
    is.read(buffer);
    is.close();

    return  new String(buffer, "UTF-8"); // use desired encoding
}
5
craig

Je suggère Arrays.toString(byte_array);

Cela dépend de votre but. Par exemple, je voulais enregistrer un tableau d'octets exactement comme le format que vous pouvez voir au moment du débogage, ce qui ressemble à ceci: [1, 2, 3] Si vous voulez enregistrer exactement la même valeur sans convertir les octets en format de caractère, Arrays.toString (byte_array) fait cela. Mais si vous voulez sauvegarder des caractères au lieu d'octets, vous devez utiliser String s = new String(byte_array). Dans ce cas, s est équivalent à [1, 2, 3] en format de caractère.

4
Questioner

La réponse précédente d'Andreas_D est bonne. Je vais simplement ajouter que partout où vous affichez la sortie, il y aura une police et un codage de caractères, qui peuvent ne pas prendre en charge certains caractères.

Pour savoir si c'est Java ou votre affichage qui pose problème, procédez comme suit:

    for(int i=0;i<str.length();i++) {
        char ch = str.charAt(i);
        System.out.println(i+" : "+ch+" "+Integer.toHexString(ch)+((ch=='\ufffd') ? " Unknown character" : ""));
    }

Java aura associé tous les caractères qu’il ne comprend pas à 0xfffd le caractère officiel des caractères inconnus. Si vous voyez un '?' dans la sortie, mais il n'est pas mappé à 0xfffd, c'est votre police d'affichage ou votre codage qui pose problème, pas Java.

3
Simon G.