Codifica come Base64 in Java


317

Devo codificare alcuni dati nella codifica Base64 in Java. Come lo faccio? Qual è il nome della classe che fornisce un codificatore Base64?


Ho provato a usare la sun.misc.BASE64Encoderclasse, senza successo. Ho la seguente riga di codice Java 7:

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

Sto usando Eclipse. Eclipse contrassegna questa riga come un errore. Ho importato le librerie richieste:

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

Ma ancora una volta, entrambi vengono visualizzati come errori. Ho trovato un post simile qui .

Ho usato Apache Commons come soluzione suggerita includendo:

import org.apache.commons.*;

e importazione dei file JAR scaricati da: http://commons.apache.org/codec/

Ma il problema esiste ancora. Eclipse mostra ancora gli errori precedentemente menzionati. Cosa dovrei fare?


7
Il mio consiglio: leggi il messaggio di errore e cerca di capire cosa dice.
JB Nizet,

27
Non dovresti usare le lezioni sottosun.**
onon15,

16
Non fanno parte dell'API pubblica; possono essere modificati, rimossi o altro senza preavviso. Alcuni di essi possono essere sperimentali o semplicemente non di livello produttivo. oracle.com/technetwork/java/faq-sun-packages-142232.html
onon15

5
Oppure utilizzare JAXB DatatypeConverter che è incluso come standard in Java 6 e versioni successive.
Ian Roberts,

9
java.util.Base64 è disponibile in Java 8
earcam il

Risposte:


621

Devi cambiare l'importazione della tua classe:

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

E quindi cambia la tua classe per usare la classe Base64.

Ecco qualche esempio di codice:

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

Quindi leggi perché non dovresti usare i pacchetti sun. * .


Aggiornamento (16-12-2016)

Ora puoi usare java.util.Base64con Java 8. Innanzitutto, importalo come fai normalmente:

import java.util.Base64;

Quindi utilizzare i metodi statici Base64 come segue:

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

Se si desidera codificare direttamente la stringa e ottenere il risultato come stringa codificata, è possibile utilizzare questo:

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

Vedere la documentazione Java per Base64 per ulteriori informazioni.


Devo scaricare qualche pacchetto esterno affinché funzioni? Se si quale?
interrotto il

2
No, non è necessario scaricare nulla
afaik

16
org.apache.commons.codec.binary.Base64 non sembra una libreria predefinita. Immagino che tu debba includere i comuni di Apache per questo. Destra?
Robert Reiz,

@Frank Decodifica i byte in una volta che genera l'errore OutOfMemory. Qualsiasi idea lo elabora nel buffer
xyz

225

Usa la classe Java-mai-troppo-tardi-per-partecipare-al-divertimento: java.util.Base64

new String(Base64.getEncoder().encode(bytes));

11
Anche se un commento banale, nota che se usi non sei compatibile con le versioni precedenti di Java, che sono (almeno a questo punto nel tempo) probabilmente molto più diffuse.
dcoder

Vorrei anche scegliere la classe di Java 8 è possibile. Attualmente sto lavorando a una classe per rimuovere la libreria dei commons apache dal nostro progetto di primavera. La maggior parte delle cose può essere sostituita facilmente con il metodo delle librerie Spring o jdk.
Adrian Cosma,

68

In Java 8 può essere fatto come: Base64.getEncoder (). EncodeToString (string.getBytes (StandardCharsets.UTF_8))

Ecco un breve esempio completo e indipendente:

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

Produzione:

old crow medicine show => b2xkIGNyb3cgbWVkaWNpbmUgc2hvdw==

3
Perché non ci sono costanti Charset nella libreria standard Java, oh perché ?!
Lukasz Wiktor,

4
Bella domanda, Lukasz! In realtà ci sono. Ho dimenticato! java.nio.charset.StandardCharsets. Modificherò la mia risposta. Vedi stackoverflow.com/questions/1684040/…
Kirby

67

Puoi anche convertire usando la codifica Base64. Per fare questo, puoi usare iljavax.xml.bind.DatatypeConverter#printBase64Binary metodo.

Per esempio:

byte[] salt = new byte[] { 50, 111, 8, 53, 86, 35, -19, -47 };
System.out.println(DatatypeConverter.printBase64Binary(salt));

4
Mentre funziona, la documentazione specifica nello specifico: DatatypeConverterInterface è solo per uso del provider JAXB.
gebirgsbärbel,

11
Penso che @gebirgsbaerbel sia sbagliato, il metodo printX () e parseX () possono essere utilizzati da qualsiasi, l'unica cosa che è solo per JAXB è il setDatatypeConverter()metodo (che quindi deve essere chiamato per i provider JAXB).
PhoneixS,

9
Alla fine la classe Base64 da Java 8 sarà la strada da percorrere. Ma se nel frattempo devi scegliere come target Java 7, questa soluzione è piacevole poiché non si basa su librerie esterne.
dana,

4
Questo non funziona con Java 9. Peggio ancora, il codice compilato per Java 7 usando javax.xml.bind. * Non funzionerà durante l'esecuzione in Java 9.
Stephen M -on strike -

21

Google Guava è un'altra scelta per codificare e decodificare i dati Base64:

Configurazione POM:

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

Codice di esempio:

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

10

Eclipse fornisce un errore / avviso perché si sta tentando di utilizzare classi interne specifiche di un fornitore JDK e che non fanno parte dell'API pubblica. Jakarta Commons fornisce la propria implementazione di codec base64, che ovviamente risiedono in un pacchetto diverso. Elimina quelle importazioni e lascia che Eclipse importi le classi Commons appropriate per te.


Il progetto Jakarta non è più . È stato mescolato e abbinato (e il nome riutilizzato per Java EE ). Puoi aggiornare la tua risposta e fornire alcuni riferimenti? Ad esempio, ora è Base64in classeorg.apache.commons.codec.binary ? È ora Apache Commons per questo contesto?
Peter Mortensen,

9

Per convertirlo, hai bisogno di un codificatore e decodificatore che otterrai da Base64Coder - un codificatore / decodificatore Base64 open source in Java . È necessario il file Base64Coder.java .

Ora per accedere a questa classe secondo le tue necessità avrai bisogno della classe seguente:

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

In Android è possibile convertire la bitmap in Base64 per il caricamento su un server o un servizio Web.

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

Questa "immagine codificata" è una rappresentazione testuale dell'immagine. Puoi utilizzarlo sia a scopo di caricamento che per la visualizzazione diretta in una pagina HTML come di seguito ( riferimento ):

<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" />

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


L'ultimo collegamento (dwij.co.in) è interrotto (404).
Peter Mortensen,


9

Ecco i miei due centesimi ... Java 8 contiene la propria implementazione di Base64 . Tuttavia, ho trovato una differenza leggermente inquietante. Per illustrare, fornirò un esempio di codice:

Il mio wrapper di 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 di prova:

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

PRODUZIONE:

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)

Si noti che il testo codificato Apache contiene interruzioni di riga aggiuntive (spazi bianchi) alla fine. Pertanto, affinché il mio codec producesse lo stesso risultato indipendentemente dall'implementazione di Base64, ho dovuto chiamare trim()il testo codificato Apache. Nel mio caso, ho semplicemente aggiunto la suddetta chiamata al metodo del mio codec apacheDecode()come segue:

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

Una volta apportata questa modifica, i risultati sono quelli che mi aspettavo di iniziare:

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!

CONCLUSIONE : Se si desidera passare da Apache Base64 a Java, è necessario:

  1. Decodifica il testo codificato con il decodificatore Apache.
  2. Codifica il testo (normale) risultante con Java.

Se cambi senza seguire questi passaggi, molto probabilmente ti imbatterai in problemi. È così che ho fatto questa scoperta.


8

Su Android, usa i metodi statici della classe di utilità android.util.Base64 . La documentazione di riferimento afferma che la classe Base64 è stata aggiunta nel livello API 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));

Questa è la risposta migliore se stai sviluppando per Android e non puoi usare Java 8.
Craig Brown,

6

Apache Commons ha una bella implementazione di Base64. Puoi farlo semplicemente come:

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

Puoi trovare maggiori dettagli sulla codifica Base64 nella codifica Base64 usando Java e JavaScript .


Si noti che ciò presuppone che la stringa sia codificata nel set di caratteri predefinito
Kirby

6

Se si utilizza Spring Framework almeno la versione 4.1, è possibile utilizzare la classe org.springframework.util.Base64Utils :

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

Delegherà a Base64 di Java 8, Apache Commons Codec o JAXB DatatypeConverter, a seconda di ciò che è disponibile.


4

Esempio semplice con Java 8:

import java.util.Base64;

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

3

In Java 7 ho codificato questo metodo

import javax.xml.bind.DatatypeConverter;

public static String toBase64(String data) {
    return DatatypeConverter.printBase64Binary(data.getBytes());
}

Funziona con Java 7 e 8, ma non con Java 9. Peggio ancora, se lo costruisci con Java 7 o 8, verrà compilato e otterrai una ClassDefNotFoundException in fase di esecuzione sotto Java 9.
Stephen M -on strike-


1

Ho provato con il seguente frammento di codice. Ha funzionato bene :-)

com.sun.org.apache.xml.internal.security.utils.Base64.encode("The string to encode goes here");

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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.