Encodage en Base64 en Java

317

J'ai besoin d'encoder certaines données dans l'encodage Base64 en Java. Comment je fais ça? Quel est le nom de la classe qui fournit un encodeur Base64?


J'ai essayé d'utiliser la sun.misc.BASE64Encoderclasse, sans succès. J'ai la ligne suivante de code Java 7:

wr.write(new sun.misc.BASE64Encoder().encode(buf));

J'utilise Eclipse. Eclipse marque cette ligne comme une erreur. J'ai importé les bibliothèques requises:

import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;

Mais encore une fois, les deux sont affichés comme des erreurs. J'ai trouvé un article similaire ici .

J'ai utilisé Apache Commons comme solution suggérée en incluant:

import org.apache.commons.*;

et importation des fichiers JAR téléchargés depuis: http://commons.apache.org/codec/

Mais le problème existe toujours. Eclipse affiche toujours les erreurs mentionnées précédemment. Que devrais-je faire?

Jury A
la source
7
Mon conseil: lisez le message d'erreur et essayez de comprendre ce qu'il dit.
JB Nizet
27
Vous n'êtes pas censé utiliser des cours de moins desun.**
onon15
16
Ils ne font pas partie de l'API publique; ils peuvent être modifiés, supprimés ou autre sans préavis. Certains d'entre eux peuvent être expérimentaux ou tout simplement pas de qualité production. oracle.com/technetwork/java/faq-sun-packages-142232.html
onon15
5
Ou utilisez le JAXB DatatypeConverter qui est inclus en standard dans Java 6 et versions ultérieures.
Ian Roberts
9
java.util.Base64 est disponible dans Java 8
earcam

Réponses:

621

Vous devez modifier l'importation de votre classe:

import org.apache.commons.codec.binary.Base64;

Et puis changez votre classe pour utiliser la classe Base64.

Voici un exemple de code:

byte[] encodedBytes = Base64.encodeBase64("Test".getBytes());
System.out.println("encodedBytes " + new String(encodedBytes));
byte[] decodedBytes = Base64.decodeBase64(encodedBytes);
System.out.println("decodedBytes " + new String(decodedBytes));

Lisez ensuite pourquoi vous ne devriez pas utiliser les packages sun. * .


Mise à jour (2016-12-16)

Vous pouvez maintenant l'utiliser java.util.Base64avec Java 8. D'abord, importez-le comme vous le faites normalement:

import java.util.Base64;

Utilisez ensuite les méthodes statiques Base64 comme suit:

byte[] encodedBytes = Base64.getEncoder().encode("Test".getBytes());
System.out.println("encodedBytes " + new String(encodedBytes));
byte[] decodedBytes = Base64.getDecoder().decode(encodedBytes);
System.out.println("decodedBytes " + new String(decodedBytes));

Si vous souhaitez directement coder une chaîne et obtenir le résultat sous forme de chaîne codée, vous pouvez utiliser ceci:

String encodeBytes = Base64.getEncoder().encodeToString((userName + ":" + password).getBytes());

Voir la documentation Java pour Base64 pour plus.

Franc
la source
Dois-je télécharger un package externe pour que cela fonctionne? Si oui, lequel?
avorté le
2
Non, vous n'avez pas besoin de télécharger quoi que ce soit afaik
pratnala
16
org.apache.commons.codec.binary.Base64 ne ressemble pas à une bibliothèque par défaut. Je suppose que vous devez inclure Apache Common pour cela. Droite?
Robert Reiz
@Frank Décoder les octets à la fois soulève l'erreur OutOfMemory.Toute idée le traite dans le tampon
xyz
225

Utilisez la classe jamais trop tardive pour participer à l'amusement de Java 8: java.util.Base64

new String(Base64.getEncoder().encode(bytes));
bratan
la source
11
Bien qu'il s'agisse d'un commentaire trivial, notez que si vous utilisez cela, vous n'êtes pas compatible avec les anciennes versions de Java, qui sont (au moins à ce stade) probablement beaucoup plus répandues.
dcoder
Je choisirais également la classe de Java 8 est possible. Je travaille actuellement sur une classe pour supprimer la bibliothèque apache commons de notre projet de printemps. La plupart des choses peuvent être remplacées facilement avec la méthode des bibliothèques Spring ou jdk.
Adrian Cosma
68

En Java 8, cela peut être fait comme: Base64.getEncoder (). EncodeToString (string.getBytes (StandardCharsets.UTF_8))

Voici un court exemple complet et autonome:

import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Temp {
    public static void main(String... args) throws Exception {
        final String s = "old crow medicine show";
        final byte[] authBytes = s.getBytes(StandardCharsets.UTF_8);
        final String encoded = Base64.getEncoder().encodeToString(authBytes);
        System.out.println(s + " => " + encoded);
    }
}

Production:

old crow medicine show => b2xkIGNyb3cgbWVkaWNpbmUgc2hvdw==
Kirby
la source
3
Pourquoi n'y a-t-il pas de constantes Charset dans la bibliothèque standard Java, oh pourquoi?!
Lukasz Wiktor
4
Bonne question, Lukasz! En fait, il y en a. J'ai oublié! java.nio.charset.StandardCharsets. Je vais modifier ma réponse. Voir stackoverflow.com/questions/1684040/…
Kirby
67

Vous pouvez également convertir en utilisant l'encodage Base64. Pour ce faire, vous pouvez utiliser lejavax.xml.bind.DatatypeConverter#printBase64Binary méthode.

Par exemple:

byte[] salt = new byte[] { 50, 111, 8, 53, 86, 35, -19, -47 };
System.out.println(DatatypeConverter.printBase64Binary(salt));
stinepike
la source
4
Pendant que cela fonctionne, la documentation indique spécifiquement: DatatypeConverterInterface est réservé à l'usage du fournisseur JAXB.
gebirgsbärbel
11
Je pense que @gebirgsbaerbel est faux, la méthode printX () et parseX () peut être utilisée par n'importe qui, la seule chose qui est uniquement pour JAXB est la setDatatypeConverter()méthode (qui doit alors être appelée pour les fournisseurs JAXB).
PhoneixS
9
Finalement, la classe Base64 de Java 8 sera la voie à suivre. Mais si vous devez cibler Java 7 entre-temps, cette solution est intéressante car elle ne repose pas sur des bibliothèques externes.
dana
4
Cela ne fonctionne pas sous Java 9. Pire encore, le code compilé pour Java 7 à l'aide de javax.xml.bind. * Échouera au moment de l'exécution sous Java 9.
Stephen M -on strike-
21

Google Guava est un autre choix pour encoder et décoder les données Base64:

Configuration POM:

<dependency>
   <artifactId>guava</artifactId>
   <groupId>com.google.guava</groupId>
   <type>jar</type>
   <version>14.0.1</version>
</dependency>

Exemple de code:

String inputContent = "Hello Việt Nam";
String base64String = BaseEncoding.base64().encode(inputContent.getBytes("UTF-8"));

// Decode
System.out.println("Base64:" + base64String); // SGVsbG8gVmnhu4d0IE5hbQ==
byte[] contentInBytes = BaseEncoding.base64().decode(base64String);
System.out.println("Source content: " + new String(contentInBytes, "UTF-8")); // Hello Việt Nam
Tho
la source
10

Eclipse vous donne une erreur / un avertissement car vous essayez d'utiliser des classes internes spécifiques à un fournisseur JDK et ne faisant pas partie de l'API publique. Jakarta Commons fournit sa propre implémentation de codecs base64, qui résident bien sûr dans un package différent. Supprimez ces importations et laissez Eclipse importer les classes Commons appropriées pour vous.

Marko Topolnik
la source
Le projet de Jakarta n'est plus . Il a été mélangé et apparié (et le nom a été réutilisé pour Java EE ). Pouvez-vous mettre à jour votre réponse et fournir des références? Par exemple, est - il maintenant classe Base64enorg.apache.commons.codec.binary ? Est-ce maintenant Apache Commons dans ce contexte?
Peter Mortensen
9

Pour convertir cela, vous avez besoin d'un encodeur et d'un décodeur que vous obtiendrez de Base64Coder - un encodeur / décodeur Base64 open source en Java . C'est le fichier Base64Coder.java dont vous aurez besoin.

Maintenant, pour accéder à cette classe selon vos besoins, vous aurez besoin de la classe ci-dessous:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Base64 {

    public static void main(String args[]) throws IOException {
        /*
         * if (args.length != 2) {
         *     System.out.println(
         *         "Command line parameters: inputFileName outputFileName");
         *     System.exit(9);
         * } encodeFile(args[0], args[1]);
         */
        File sourceImage = new File("back3.png");
        File sourceImage64 = new File("back3.txt");
        File destImage = new File("back4.png");
        encodeFile(sourceImage, sourceImage64);
        decodeFile(sourceImage64, destImage);
    }

    private static void encodeFile(File inputFile, File outputFile) throws IOException {
        BufferedInputStream in = null;
        BufferedWriter out = null;
        try {
            in = new BufferedInputStream(new FileInputStream(inputFile));
            out = new BufferedWriter(new FileWriter(outputFile));
            encodeStream(in, out);
            out.flush();
        }
        finally {
            if (in != null)
                in.close();
            if (out != null)
                out.close();
        }
    }

    private static void encodeStream(InputStream in, BufferedWriter out) throws IOException {
        int lineLength = 72;
        byte[] buf = new byte[lineLength / 4 * 3];
        while (true) {
            int len = in.read(buf);
            if (len <= 0)
                break;
            out.write(Base64Coder.encode(buf, 0, len));
            out.newLine();
        }
    }

    static String encodeArray(byte[] in) throws IOException {
        StringBuffer out = new StringBuffer();
        out.append(Base64Coder.encode(in, 0, in.length));
        return out.toString();
    }

    static byte[] decodeArray(String in) throws IOException {
        byte[] buf = Base64Coder.decodeLines(in);
        return buf;
    }

    private static void decodeFile(File inputFile, File outputFile) throws IOException {
        BufferedReader in = null;
        BufferedOutputStream out = null;
        try {
            in = new BufferedReader(new FileReader(inputFile));
            out = new BufferedOutputStream(new FileOutputStream(outputFile));
            decodeStream(in, out);
            out.flush();
        }
        finally {
            if (in != null)
                in.close();
            if (out != null)
                out.close();
        }
    }

    private static void decodeStream(BufferedReader in, OutputStream out) throws IOException {
        while (true) {
            String s = in.readLine();
            if (s == null)
                break;
            byte[] buf = Base64Coder.decodeLines(s);
            out.write(buf);
        }
    }
}

Dans Android, vous pouvez convertir votre bitmap en Base64 pour le télécharger sur un serveur ou un service Web.

Bitmap bmImage = //Data
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmImage.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] imageData = baos.toByteArray();
String encodedImage = Base64.encodeArray(imageData);

Cette «encodedImage» est une représentation textuelle de votre image. Vous pouvez l'utiliser pour télécharger ou pour afficher directement dans une page HTML comme ci-dessous ( référence ):

<img alt="" src="data:image/png;base64,<?php echo $encodedImage; ?>" width="100px" />
<img alt="" src="data:image/png;base64,/9j/4AAQ...........1f/9k=" width="100px" />

Documentation: http://dwij.co.in/java-base64-image-encoder

Développeur Web à Pune
la source
Le dernier lien (dwij.co.in) est rompu (404).
Peter Mortensen
9

Voici mes deux cents ... Java 8 contient sa propre implémentation de Base64 . Cependant, j'ai trouvé une différence légèrement inquiétante. Pour illustrer, je vais fournir un exemple de code:

Mon wrapper de codec:

public interface MyCodec
{
  static String apacheDecode(String encodedStr)
  {
    return new String(Base64.decodeBase64(encodedStr), Charset.forName("UTF-8"));
  }

  static String apacheEncode(String decodedStr)
  {
    byte[] decodedByteArr = decodedStr.getBytes(Charset.forName("UTF-8"));
    return Base64.encodeBase64String(decodedByteArr);
  }

  static String javaDecode(String encodedStr)
  {
    return new String(java.util.Base64.getDecoder().decode(encodedStr), Charset.forName("UTF-8"));
  }

  static String javaEncode(String decodedStr)
  {
    byte[] decodedByteArr = decodedStr.getBytes(Charset.forName("UTF-8"));
    return java.util.Base64.getEncoder().encodeToString(decodedByteArr);
  }
}

Classe de test:

public class CodecDemo
{
  public static void main(String[] args)
  {
    String decodedText = "Hello World!";

    String encodedApacheText = MyCodec.apacheEncode(decodedText);
    String encodedJavaText = MyCodec.javaEncode(decodedText);

    System.out.println("Apache encoded text: " + MyCodec.apacheEncode(encodedApacheText));
    System.out.println("Java encoded text: " + MyCodec.javaEncode(encodedJavaText));

    System.out.println("Encoded results equal: " + encodedApacheText.equals(encodedJavaText));

    System.out.println("Apache decode Java: " + MyCodec.apacheDecode(encodedJavaText));
    System.out.println("Java decode Java: " + MyCodec.javaDecode(encodedJavaText));

    System.out.println("Apache decode Apache: " + MyCodec.apacheDecode(encodedApacheText));
    System.out.println("Java decode Apache: " + MyCodec.javaDecode(encodedApacheText));
  }
}

PRODUCTION:

Apache encoded text: U0dWc2JHOGdWMjl5YkdRaA0K

Java encoded text: U0dWc2JHOGdWMjl5YkdRaA==
Encoded results equal: false
Apache decode Java: Hello World!
Java decode Java: Hello World!
Apache decode Apache: Hello World!
Exception in thread "main" java.lang.IllegalArgumentException: Illegal base64 character d
    at java.util.Base64$Decoder.decode0(Base64.java:714)
    at java.util.Base64$Decoder.decode(Base64.java:526)
    at java.util.Base64$Decoder.decode(Base64.java:549)

Notez que le texte codé Apache contient des sauts de ligne supplémentaires (espaces blancs) à la fin. Par conséquent, pour que mon codec donne le même résultat quelle que soit l'implémentation Base64, j'ai dû faire appel trim()au texte codé Apache. Dans mon cas, j'ai simplement ajouté l'appel de méthode susmentionné à mon codec apacheDecode()comme suit:

return Base64.encodeBase64String(decodedByteArr).trim();

Une fois ce changement effectué, les résultats sont ceux que j'attendais au départ:

Apache encoded text: U0dWc2JHOGdWMjl5YkdRaA==
Java encoded text: U0dWc2JHOGdWMjl5YkdRaA==
Encoded results equal: true
Apache decode Java: Hello World!
Java decode Java: Hello World!
Apache decode Apache: Hello World!
Java decode Apache: Hello World!

CONCLUSION : Si vous souhaitez passer d'Apache Base64 à Java, vous devez:

  1. Décodez le texte encodé avec votre décodeur Apache.
  2. Encode le texte (brut) résultant avec Java.

Si vous passez sans suivre ces étapes, vous rencontrerez très probablement des problèmes. C'est ainsi que j'ai fait cette découverte.

hfontanez
la source
8

Sur Android, utilisez les méthodes statiques de la classe d'utilitaires android.util.Base64 . La documentation référencée indique que la classe Base64 a été ajoutée dans l'API niveau 8 ( Android 2.2 (Froyo)).

import android.util.Base64;

byte[] encodedBytes = Base64.encode("Test".getBytes());
Log.d("tag", "encodedBytes " + new String(encodedBytes));

byte[] decodedBytes = Base64.decode(encodedBytes);
Log.d("tag", "decodedBytes " + new String(decodedBytes));
Yojimbo
la source
C'est la meilleure réponse si vous développez pour Android et que vous ne pouvez pas utiliser Java 8.
Craig Brown
6

Apache Commons a une belle implémentation de Base64. Vous pouvez le faire aussi simplement que:

// Encrypt data on your side using BASE64
byte[] bytesEncoded = Base64.encodeBase64(str .getBytes());
System.out.println("ecncoded value is " + new String(bytesEncoded));

// Decrypt data on other side, by processing encoded data
byte[] valueDecoded= Base64.decodeBase64(bytesEncoded );
System.out.println("Decoded value is " + new String(valueDecoded));

Vous pouvez trouver plus de détails sur l'encodage base64 à l'encodage Base64 en utilisant Java et JavaScript .

faisalbhagat
la source
Notez que cela suppose que la chaîne est encodée dans le jeu de caractères par défaut
Kirby
6

Si vous utilisez Spring Framework au moins la version 4.1, vous pouvez utiliser la classe org.springframework.util.Base64Utils :

byte[] raw = { 1, 2, 3 };
String encoded = Base64Utils.encodeToString(raw);
byte[] decoded = Base64Utils.decodeFromString(encoded);

Il sera délégué à Base64 de Java 8, Codec Apache Commons ou JAXB DatatypeConverter, selon ce qui est disponible.

holmis83
la source
4

Exemple simple avec Java 8:

import java.util.Base64;

String str = "your string";
String encodedStr = Base64.getEncoder().encodeToString(str.getBytes("utf-8"));
z3d0
la source
3

Dans Java 7, j'ai codé cette méthode

import javax.xml.bind.DatatypeConverter;

public static String toBase64(String data) {
    return DatatypeConverter.printBase64Binary(data.getBytes());
}
Daniel De León
la source
Fonctionne sous Java 7 et 8, mais pas Java 9. Pire, si vous le construisez sous Java 7 ou 8, il se construira et vous obtiendrez une exception ClassDefNotFoundException au moment de l'exécution sous Java 9.
Stephen M -on strike-
1

J'ai essayé avec l'extrait de code suivant. Cela a bien fonctionné. :-)

com.sun.org.apache.xml.internal.security.utils.Base64.encode("The string to encode goes here");
tmh
la source
0
public String convertImageToBase64(String filePath) {
    byte[] fileContent = new byte[0];
    String base64encoded = null;
    try {
        fileContent = FileUtils.readFileToByteArray(new File(filePath));
    } catch (IOException e) {
        log.error("Error reading file: {}", filePath);
    }
    try {
        base64encoded = Base64.getEncoder().encodeToString(fileContent);
    } catch (Exception e) {
        log.error("Error encoding the image to base64", e);
    }
    return base64encoded;
}
ghandour abdelkrim
la source