Codierung als Base64 in Java

317

Ich muss einige Daten in der Base64-Codierung in Java codieren. Wie mache ich das? Wie heißt die Klasse, die einen Base64-Encoder bereitstellt?


Ich habe versucht, die sun.misc.BASE64EncoderKlasse zu benutzen , ohne Erfolg. Ich habe die folgende Zeile von Java 7-Code:

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

Ich benutze Eclipse. Eclipse markiert diese Zeile als Fehler. Ich habe die erforderlichen Bibliotheken importiert:

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

Aber auch hier werden beide als Fehler angezeigt. Ich habe hier einen ähnlichen Beitrag gefunden .

Ich habe Apache Commons als Lösung verwendet, indem ich Folgendes vorgeschlagen habe:

import org.apache.commons.*;

und Importieren der JAR-Dateien, die heruntergeladen wurden von: http://commons.apache.org/codec/

Das Problem besteht jedoch weiterhin. Eclipse zeigt weiterhin die zuvor genannten Fehler an. Was sollte ich tun?

Jury A.
quelle
7
Mein Rat: Lesen Sie die Fehlermeldung und versuchen Sie zu verstehen, was darin steht.
JB Nizet
27
Sie sollten keine Klassen untersun.**
onon15
16
Sie sind nicht Teil der öffentlichen API. Sie können ohne vorherige Ankündigung geändert, entfernt oder was auch immer. Einige von ihnen sind möglicherweise experimentell oder einfach nicht in Produktionsqualität. oracle.com/technetwork/java/faq-sun-packages-142232.html
onon15
5
Oder verwenden Sie den JAXB DatatypeConverter, der standardmäßig in Java 6 und höher enthalten ist.
Ian Roberts
9
java.util.Base64 ist in Java 8 verfügbar
earcam

Antworten:

621

Sie müssen den Import Ihrer Klasse ändern:

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

Ändern Sie dann Ihre Klasse, um die Base64-Klasse zu verwenden.

Hier ist ein Beispielcode:

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

Lesen Sie dann, warum Sie sun. * -Pakete nicht verwenden sollten .


Update (2016-12-16)

Sie können es jetzt java.util.Base64mit Java 8 verwenden. Importieren Sie es zunächst wie gewohnt:

import java.util.Base64;

Verwenden Sie dann die statischen Base64-Methoden wie folgt:

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

Wenn Sie eine Zeichenfolge direkt codieren und das Ergebnis als codierte Zeichenfolge erhalten möchten, können Sie Folgendes verwenden:

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

Sehen Informationen finden Java-Dokumentation zu Base64 .

Frank
quelle
Muss ich ein externes Paket herunterladen, damit dies funktioniert? Wenn ja, welche?
abgebrochen
2
Nein, Sie müssen nichts herunterladen afaik
pratnala
16
org.apache.commons.codec.binary.Base64 sieht nicht wie eine Standardbibliothek aus. Ich denke, Sie müssen dafür Apache Commons einschließen. Recht?
Robert Reiz
@Frank Das Decodieren der Bytes auf einmal löst einen OutOfMemory-Fehler aus. Jede Idee verarbeitet sie im Puffer
xyz
Bitte setzen Sie das Update über die alte Lösung.
Zon
225

Verwenden Sie die nie zu spät kommende Java 8-Klasse, um am Spaß teilzunehmen: java.util.Base64

new String(Base64.getEncoder().encode(bytes));
Bratan
quelle
11
Beachten Sie, dass Sie, obwohl dies ein trivialer Kommentar ist, nicht mit älteren Java-Versionen kompatibel sind, die (zumindest zu diesem Zeitpunkt) wahrscheinlich weitaus häufiger vorkommen.
dcoder
Ich würde auch wählen, Java 8 Klasse ist möglich. Ich arbeite derzeit an einer Klasse, um die Apache Commons-Bibliothek aus unserem Frühlingsprojekt zu entfernen. Die meisten Dinge können einfach durch Methoden aus Spring-Bibliotheken oder jdk ersetzt werden.
Adrian Cosma
68

In Java 8 kann dies wie folgt erfolgen: Base64.getEncoder (). EncodeToString (string.getBytes (StandardCharsets.UTF_8))

Hier ist ein kurzes, in sich geschlossenes vollständiges Beispiel:

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

Ausgabe:

old crow medicine show => b2xkIGNyb3cgbWVkaWNpbmUgc2hvdw==
Kirby
quelle
3
Warum gibt es in der Java-Standardbibliothek keine Zeichensatzkonstanten, oh warum?!
Lukasz Wiktor
4
Gute Frage, Lukasz! Eigentlich gibt es. Ich habe vergessen! java.nio.charset.StandardCharsets. Ich werde meine Antwort bearbeiten. Siehe stackoverflow.com/questions/1684040/…
Kirby
67

Sie können auch mit Base64-Codierung konvertieren. Dazu können Sie die verwendenjavax.xml.bind.DatatypeConverter#printBase64Binary Methode verwenden.

Zum Beispiel:

byte[] salt = new byte[] { 50, 111, 8, 53, 86, 35, -19, -47 };
System.out.println(DatatypeConverter.printBase64Binary(salt));
Stinepike
quelle
4
Während dies funktioniert, heißt es in der Dokumentation speziell: DatatypeConverterInterface ist nur für JAXB-Anbieter bestimmt.
gebirgsbärbel
11
Ich denke, dass @gebirgsbaerbel falsch ist, printX () und parseX () können von jedem verwendet werden. Das einzige, was nur für JAXB gilt, ist die setDatatypeConverter()Methode (die dann für JAXB-Anbieter aufgerufen werden muss).
PhoneixS
9
Schließlich wird die Base64 - Klasse von Java 8 wird der Weg zu gehen. Wenn Sie jedoch in der Zwischenzeit auf Java 7 abzielen müssen, ist diese Lösung hilfreich, da sie nicht auf externen Bibliotheken basiert.
Dana
4
Dies funktioniert nicht unter Java 9. Schlimmer noch, Code, der mit javax.xml.bind für Java 7 kompiliert wurde. * Schlägt zur Laufzeit unter Java 9 fehl.
Stephen M - am Streik -
21

Google Guava ist eine weitere Option zum Codieren und Decodieren von Base64-Daten:

POM-Konfiguration:

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

Beispielcode:

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
quelle
10

Eclipse gibt einen Fehler / eine Warnung aus, da Sie versuchen, interne Klassen zu verwenden, die für einen JDK-Anbieter spezifisch sind und nicht Teil der öffentlichen API sind. Jakarta Commons bietet eine eigene Implementierung von base64-Codecs an, die sich natürlich in einem anderen Paket befinden. Löschen Sie diese Importe und lassen Sie Eclipse die richtigen Commons-Klassen für Sie importieren.

Marko Topolnik
quelle
Das Jakarta-Projekt gibt es nicht mehr . Es wurde gemischt und abgeglichen (und der Name für Java EE wiederverwendet ). Können Sie Ihre Antwort aktualisieren und einige Referenzen angeben? Ist es zum Beispiel jetzt Klasse Base64inorg.apache.commons.codec.binary ? Ist es jetzt Apache Commons für diesen Kontext?
Peter Mortensen
Sie können gerne meine Antwort bearbeiten.
Marko Topolnik
9

Um dies zu konvertieren, benötigen Sie einen Encoder und Decoder, den Sie von Base64Coder erhalten - einem Open-Source-Base64-Encoder / Decoder in Java . Es ist die Datei Base64Coder.java, die Sie benötigen.

Um nun gemäß Ihren Anforderungen auf diese Klasse zugreifen zu können, benötigen Sie die folgende Klasse:

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 können Sie Ihre Bitmap zum Hochladen auf einen Server oder Webdienst in Base64 konvertieren.

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

Dieses "encodedImage" ist eine Textdarstellung Ihres Bildes. Sie können dies entweder zum Hochladen oder zum direkten Anzeigen in eine HTML-Seite wie folgt verwenden ( Referenz ):

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

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

Webentwickler in Pune
quelle
Der letzte Link (dwij.co.in) ist defekt (404).
Peter Mortensen
9

Hier sind meine zwei Cent ... Java 8 enthält eine eigene Implementierung von Base64 . Ich fand jedoch einen etwas störenden Unterschied. Zur Veranschaulichung werde ich ein Codebeispiel bereitstellen:

Mein Codec-Wrapper:

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

Testklasse:

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

AUSGABE:

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)

Beachten Sie, dass der Apache-codierte Text am Ende zusätzliche Zeilenumbrüche (Leerzeichen) enthält. Daher musste ich trim()den Apache-codierten Text aufrufen, damit mein Codec unabhängig von der Base64-Implementierung das gleiche Ergebnis liefert . In meinem Fall habe ich den oben genannten Methodenaufruf einfach apacheDecode()wie folgt zu meinen Codecs hinzugefügt :

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

Nachdem diese Änderung vorgenommen wurde, erwartete ich zunächst folgende Ergebnisse:

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!

SCHLUSSFOLGERUNG : Wenn Sie von Apache Base64 zu Java wechseln möchten, müssen Sie:

  1. Dekodieren Sie codierten Text mit Ihrem Apache-Decoder.
  2. Codieren Sie den resultierenden (einfachen) Text mit Java.

Wenn Sie wechseln, ohne diese Schritte auszuführen, treten höchstwahrscheinlich Probleme auf. So habe ich diese Entdeckung gemacht.

hfontanez
quelle
8

Verwenden Sie unter Android die statischen Methoden der Dienstprogrammklasse android.util.Base64 . Die Dokumentation, auf die verwiesen wird, besagt, dass die Base64-Klasse in API-Level 8 ( Android 2.2 (Froyo)) hinzugefügt wurde .

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
quelle
Dies ist die beste Antwort, wenn Sie für Android entwickeln und Java 8 nicht verwenden können.
Craig Brown
6

Apache Commons hat eine schöne Implementierung von Base64. Sie können dies so einfach tun wie:

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

Weitere Informationen zur Base64-Codierung finden Sie unter Base64-Codierung mit Java und JavaScript .

faisalbhagat
quelle
Beachten Sie, dass dies voraussetzt, dass die Zeichenfolge im Standardzeichensatz
Kirby
6

Wenn Sie Spring Framework mindestens Version 4.1 verwenden, können Sie die Klasse org.springframework.util.Base64Utils verwenden :

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

Es wird an Java 8 Base64, Apache Commons Codec oder JAXB DatatypeConverter delegiert, je nachdem, was verfügbar ist.

holmis83
quelle
4

Einfaches Beispiel mit Java 8:

import java.util.Base64;

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

In Java 7 habe ich diese Methode codiert

import javax.xml.bind.DatatypeConverter;

public static String toBase64(String data) {
    return DatatypeConverter.printBase64Binary(data.getBytes());
}
Daniel De León
quelle
Funktioniert unter Java 7 und 8, aber nicht unter Java 9. Schlimmer noch, wenn Sie dies unter Java 7 oder 8 erstellen, wird es erstellt und Sie erhalten zur Laufzeit unter Java 9 eine ClassDefNotFoundException.
Stephen M -on strike-
1

Ich habe es mit dem folgenden Code-Snippet versucht. Es hat gut funktioniert. :-)

com.sun.org.apache.xml.internal.security.utils.Base64.encode("The string to encode goes here");
tmh
quelle
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
quelle