Pengkodean sebagai Base64 di Jawa

317

Saya perlu menyandikan beberapa data dalam penyandian Base64 di Jawa. Bagaimana aku melakukan itu? Apa nama kelas yang menyediakan encoder Base64?


Saya mencoba menggunakan sun.misc.BASE64Encoderkelas, tetapi tidak berhasil. Saya memiliki baris kode Java 7 berikut:

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

Saya menggunakan Eclipse. Eclipse menandai baris ini sebagai kesalahan. Saya mengimpor perpustakaan yang diperlukan:

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

Tetapi sekali lagi, keduanya ditampilkan sebagai kesalahan. Saya menemukan pos serupa di sini .

Saya menggunakan Apache Commons sebagai solusi yang disarankan dengan memasukkan:

import org.apache.commons.*;

dan mengimpor file JAR yang diunduh dari: http://commons.apache.org/codec/

Tapi masalahnya masih ada. Eclipse masih menunjukkan kesalahan yang disebutkan sebelumnya. Apa yang harus saya lakukan?

Juri A
sumber
7
Saran saya: baca pesan kesalahan, dan cobalah untuk memahami apa yang dikatakannya.
JB Nizet
27
Anda tidak seharusnya menggunakan kelas di bawahsun.**
15
16
Mereka bukan bagian dari API publik; mereka dapat diubah, dihapus atau apa pun tanpa pemberitahuan. Beberapa dari mereka mungkin eksperimental atau tidak hanya tingkat produksi. oracle.com/technetwork/java/faq-sun-packages-142232.html
15
5
Atau gunakan JAXB DatatypeConverter yang termasuk sebagai standar dalam Java 6 dan yang lebih baru.
Ian Roberts
9
java.util.Base64 tersedia di Java 8
earcam

Jawaban:

621

Anda perlu mengubah impor kelas Anda:

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

Dan kemudian ubah kelas Anda untuk menggunakan kelas Base64.

Berikut beberapa contoh kode:

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

Kemudian baca mengapa Anda tidak harus menggunakan paket sun. * .


Pembaruan (2016-12-16)

Anda sekarang dapat menggunakan java.util.Base64dengan Java 8. Pertama, impor seperti biasa:

import java.util.Base64;

Kemudian gunakan metode statis Base64 sebagai berikut:

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

Jika Anda ingin menyandikan string secara langsung dan mendapatkan hasilnya sebagai string yang disandikan, Anda dapat menggunakan ini:

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

Lihat dokumentasi Java untuk Base64 untuk lebih lanjut.

jujur
sumber
Apakah saya perlu mengunduh paket eksternal agar ini berfungsi? Jika ya, yang mana?
dibatalkan
2
Tidak, Anda tidak perlu mengunduh apa pun afaik
pratnala
16
org.apache.commons.codec.binary.Base64 tidak terlihat seperti perpustakaan default. Saya kira Anda harus menyertakan apache commons untuk itu. Baik?
Robert Reiz
@ Jujur Mengurai kode byte sekaligus meningkatkan kesalahan OutOfMemory. Setiap ide memprosesnya dalam buffer
xyz
225

Gunakan kelas Java 8 yang tidak pernah terlambat untuk bergabung di kelas bersenang-senang: java.util.Base64

new String(Base64.getEncoder().encode(bytes));
bratan
sumber
11
Meskipun komentar sepele, perhatikan bahwa jika Anda menggunakannya Anda tidak kompatibel dengan versi Java yang lebih lama, yang (setidaknya pada titik waktu ini) mungkin jauh lebih lazim.
dcoder
Saya juga akan memilih kelas Java 8 adalah mungkin. Saat ini saya sedang mengerjakan sebuah kelas untuk menghapus perpustakaan apache commons dari proyek musim semi kami. Sebagian besar barang dapat diganti dengan mudah dengan metode dari pustaka Spring atau jdk.
Adrian Cosma
68

Di Java 8 dapat dilakukan sebagai: Base64.getEncoder (). EncodeToString (string.getBytes (StandardCharsets.UTF_8))

Berikut adalah contoh lengkap singkat dan lengkap:

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

Keluaran:

old crow medicine show => b2xkIGNyb3cgbWVkaWNpbmUgc2hvdw==
Kirby
sumber
3
Mengapa tidak ada konstanta Charset di perpustakaan standar Java, oh mengapa ?!
Lukasz Wiktor
4
Pertanyaan bagus, Lukasz! Sebenarnya ada. Saya lupa! java.nio.charset.StandardCharsets. Saya akan mengedit jawaban saya. Lihat stackoverflow.com/questions/1684040/…
Kirby
67

Anda juga dapat mengonversi menggunakan pengkodean Base64. Untuk melakukan ini, Anda dapat menggunakan javax.xml.bind.DatatypeConverter#printBase64Binarymetode ini.

Sebagai contoh:

byte[] salt = new byte[] { 50, 111, 8, 53, 86, 35, -19, -47 };
System.out.println(DatatypeConverter.printBase64Binary(salt));
stinepike
sumber
4
Sementara ini berfungsi, dokumentasi secara khusus menyatakan: DatatypeConverterInterface hanya untuk penggunaan penyedia JAXB.
gebirgsbärbel
11
Saya pikir @gebirgsbaerbel salah, metode printX () dan parseX () dapat digunakan oleh siapa saja, satu-satunya hal yang hanya untuk JAXB adalah setDatatypeConverter()metode (yang kemudian harus dipanggil untuk penyedia JAXB).
PhoneixS
9
Akhirnya kelas Base64 dari Jawa 8 akan yang cara untuk pergi. Tetapi jika Anda harus menargetkan Java 7 sementara itu, solusi ini bagus karena tidak bergantung pada perpustakaan eksternal.
dana
4
Ini tidak berfungsi di bawah Java 9. Lebih buruk lagi, kode yang dikompilasi untuk Java 7 menggunakan javax.xml.bind. * Akan gagal pada Runtime di bawah Java 9.
Stephen M -on strike-
21

Google Guava adalah pilihan lain untuk menyandikan dan mendekode data Base64:

Konfigurasi POM:

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

Kode sampel:

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

Eclipse memberi Anda kesalahan / peringatan karena Anda mencoba menggunakan kelas internal yang khusus untuk vendor JDK dan bukan bagian dari API publik. Jakarta Commons menyediakan implementasi sendiri dari base64 codec, yang tentu saja berada dalam paket yang berbeda. Hapus impor itu dan biarkan Eclipse mengimpor kelas Commons yang tepat untuk Anda.

Marko Topolnik
sumber
Proyek Jakarta tidak lagi . Ini telah dicampur dan dicocokkan (dan nama digunakan kembali untuk Java EE ). Bisakah Anda memperbarui jawaban dan memberikan beberapa referensi? Sebagai contoh, adalah sekarang kelas Base64diorg.apache.commons.codec.binary ? Apakah sekarang Apache Commons untuk konteks ini?
Peter Mortensen
9

Untuk mengonversinya, Anda memerlukan encoder & decoder yang akan Anda dapatkan dari Base64Coder - encoder / decoder Base64 sumber terbuka di Jawa . Ini adalah file Base64Coder.java yang Anda perlukan.

Sekarang untuk mengakses kelas ini sesuai kebutuhan Anda, Anda akan memerlukan kelas di bawah ini:

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

Di Android Anda dapat mengonversi bitmap Anda ke Base64 untuk diunggah ke server atau layanan web.

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

"EncodedImage" ini adalah representasi teks dari gambar Anda. Anda dapat menggunakan ini untuk tujuan mengunggah atau untuk memutar langsung ke halaman HTML seperti di bawah ini ( referensi ):

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

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

Pengembang Web di Pune
sumber
Tautan terakhir (dwij.co.in) rusak (404).
Peter Mortensen
9

Berikut adalah dua sen saya ... Java 8 memang mengandung implementasi Base64 sendiri . Namun, saya menemukan satu perbedaan yang sedikit mengganggu. Sebagai ilustrasi, saya akan memberikan contoh kode:

Pembungkus codec saya:

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

Kelas Tes:

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

KELUARAN:

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)

Perhatikan bahwa teks yang disandikan Apache berisi jeda baris tambahan (spasi putih) di bagian akhir. Oleh karena itu, agar codec saya menghasilkan hasil yang sama terlepas dari implementasi Base64, saya harus menelepontrim() teks yang disandikan Apache. Dalam kasus saya, saya cukup menambahkan pemanggilan metode yang disebutkan di atas ke codec saya apacheDecode()sebagai berikut:

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

Setelah perubahan ini dibuat, hasilnya adalah apa yang saya harapkan dimulai dengan:

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!

KESIMPULAN : Jika Anda ingin beralih dari Apache Base64 ke Java, Anda harus:

  1. Dekode teks yang disandikan dengan dekoder Apache Anda.
  2. Menyandikan teks (biasa) yang dihasilkan dengan Java.

Jika Anda beralih tanpa mengikuti langkah-langkah ini, kemungkinan besar Anda akan mengalami masalah. Begitulah cara saya membuat penemuan ini.

hfontanez
sumber
8

Di Android, gunakan metode statis dari kelas utilitas android.util.Base64 . Dokumentasi yang direferensikan mengatakan bahwa kelas Base64 ditambahkan di API level 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
sumber
Ini adalah jawaban terbaik jika Anda mengembangkan untuk Android dan Anda tidak dapat menggunakan Java 8.
Craig Brown
6

Apache Commons memiliki implementasi Base64 yang bagus. Anda dapat melakukan ini hanya dengan:

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

Anda dapat menemukan detail lebih lanjut tentang pengkodean base64 di pengkodean Base64 menggunakan Java dan JavaScript .

faisalbhagat
sumber
Perhatikan bahwa ini mengasumsikan string dikodekan dalam charset default
Kirby
6

Jika Anda menggunakan Spring Framework setidaknya versi 4.1, Anda dapat menggunakan kelas org.springframework.util.Base64Utils :

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

Ini akan mendelegasikan ke Java 8's Base64, Apache Commons Codec, atau JAXB DatatypeConverter, tergantung pada apa yang tersedia.

holmis83
sumber
4

Contoh sederhana dengan Java 8:

import java.util.Base64;

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

Di Java 7 saya memberi kode metode ini

import javax.xml.bind.DatatypeConverter;

public static String toBase64(String data) {
    return DatatypeConverter.printBase64Binary(data.getBytes());
}
Daniel De León
sumber
Berfungsi di bawah Java 7 dan 8, tetapi bukan Java 9. Lebih buruk lagi, jika Anda membangun ini di bawah Java 7 atau 8, ia akan membangun dan kemudian Anda akan mendapatkan ClassDefNotFoundException di Runtime di bawah Java 9.
Stephen M -on strike-
1

Saya mencoba dengan cuplikan kode berikut. Itu bekerja dengan baik. :-)

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