Кодування в Java як Base64


317

Мені потрібно кодувати деякі дані в кодуванні Base64 на Java. Як це зробити? Як називається клас, що забезпечує кодер Base64?


Я намагався використовувати sun.misc.BASE64Encoderклас, без успіху. У мене є такий рядок коду Java 7:

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

Я використовую Eclipse. Eclipse позначає цей рядок як помилку. Я імпортував необхідні бібліотеки:

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

Але знову ж таки, обидва вони показані як помилки. Тут я знайшов подібний пост .

Я використовував Apache Commons як рішення, яке пропонується, включаючи:

import org.apache.commons.*;

та імпорт файлів JAR, завантажених з: http://commons.apache.org/codec/

Але проблема все ще існує. Затьмарення все ще показує помилки, згадані раніше. Що я повинен зробити?


7
Моя порада: прочитайте повідомлення про помилку та спробуйте зрозуміти, що воно говорить.
JB Nizet

27
Ви не повинні використовувати заняття підsun.**
onon15,

16
Вони не входять до публічного API; вони можуть бути змінені, вилучені чи будь-що без попереднього повідомлення. Деякі з них можуть бути експериментальними або просто не виробничими. oracle.com/technetwork/java/faq-sun-packages-142232.html
onon15

5
Або використовувати JAXB DatatypeConverter, який стандартно включений у Java 6 та новіші версії.
Ян Робертс

9
java.util.Base64 доступний на Java 8
earcam

Відповіді:


621

Вам потрібно змінити імпорт класу:

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

А потім змінити свій клас, щоб використовувати клас Base64.

Ось приклад коду:

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

Потім прочитайте, чому не слід використовувати пакети . * .


Оновлення (2016-12-16)

Тепер ви можете використовувати java.util.Base64з Java 8. По-перше, імпортуйте її як зазвичай:

import java.util.Base64;

Потім використовуйте статичні методи Base64 наступним чином:

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

Якщо ви хочете безпосередньо кодувати рядок і отримувати результат як закодований рядок, ви можете використовувати це:

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

Додаткову інформацію див. У документації Java для Base64 .


Чи потрібно завантажити будь-який зовнішній пакет, щоб це працювало? Якщо так, що?
аборт

2
Ні, вам не потрібно нічого завантажувати
afaik

16
org.apache.commons.codec.binary.Base64 не схожа на бібліотеку за замовчуванням. Я здогадуюсь, що для цього вам слід включити апачі. Правильно?
Роберт Рейз

@Frank Розшифровка байтів відразу піднімає помилку OutOfMemory. Кожна ідея обробляє її в буфері
xyz

225

Використовуйте клас класу "Ніколи не пізно для приєднання до забави" Java 8: java.util.Base64

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

11
Хоча банальний коментар, зауважте, що якщо ви використовуєте, що ви не сумісні зі старими версіями Java, які (принаймні, на даний момент часу), мабуть, набагато більш поширені.
dcoder

Я також хотів би вибрати, що клас Java 8 можливий. Зараз я працюю над класом, щоб вилучити бібліотеку apache commons з нашого весняного проекту. Більшість матеріалів можна легко замінити методом з бібліотек Spring або jdk.
Адріан Косма

68

У Java 8 це можна зробити так: Base64.getEncoder (). EncodeToString (string.getBytes (StandardCharsets.UTF_8))

Ось короткий, автономний повний приклад:

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

Вихід:

old crow medicine show => b2xkIGNyb3cgbWVkaWNpbmUgc2hvdw==

3
Чому в стандартній бібліотеці Java немає констант Charset, о, чому ?!
Лукаш Віктор

4
Добре запитання, Лукаш! Власне, є. Я забув! java.nio.charset.StandardCharsets. Я відредагую свою відповідь. Дивіться stackoverflow.com/questions/1684040/…
Кірбі

67

Ви також можете конвертувати за допомогою кодування Base64. Для цього можна скористатися javax.xml.bind.DatatypeConverter#printBase64Binaryметодом.

Наприклад:

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

4
Хоча це працює, у документації спеціально зазначено: DatatypeConverterInterface призначений тільки для постачальника JAXB.
gebirgsbärbel

11
Я думаю, що @gebirgsbaerbel помиляється, метод printX () та parseX () може використовуватися будь-яким, єдине, що стосується лише JAXB - це setDatatypeConverter()метод (який тоді потрібно викликати для постачальників JAXB).
PhoneixS

9
В кінці кінців , клас Base64 з Java 8 буде шлях. Але якщо вам доводиться орієнтуватися на Java 7 тим часом, це рішення добре, оскільки не покладається на зовнішні бібліотеки.
дата

4
Це не працює під Java 9. Гірше, що код, складений для Java 7 за допомогою javax.xml.bind. * Не вдасться під час виконання під Java 9.
Стівен М - страйк -

21

Google Guava - це ще один вибір кодування та декодування даних Base64:

Конфігурація POM:

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

Приклад коду:

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 видає вам помилку / попередження, оскільки ви намагаєтесь використовувати внутрішні класи, специфічні для постачальника JDK і не є частиною загальнодоступного API. Jakarta Commons пропонує власну реалізацію базових кодеків64, які, звичайно, містяться в іншому пакеті. Видаліть цей імпорт і дозвольте Eclipse імпортувати відповідні класи Commons для вас.


Проект Джакарта вже не є . Він змішаний і збігається (і назва повторно використовується для Java EE ). Чи можете ви оновити свою відповідь та надати кілька посилань? Наприклад, це зараз клас Base64уorg.apache.commons.codec.binary ? Чи є зараз Apache Commons для цього контексту?
Пітер Мортенсен

9

Щоб перетворити це, вам потрібен кодер і декодер, який ви отримаєте від Base64Coder - кодера / декодера Base64 з відкритим кодом на Java . Це файл Base64Coder.java, який вам знадобиться.

Тепер для доступу до цього класу відповідно до вашої вимоги вам знадобиться клас нижче:

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

В Android ви можете перетворити свою растрову карту в Base64 для завантаження на сервер або веб-сервіс.

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

Цей "encodedImage" - це текстове зображення вашого зображення. Ви можете використовувати це для завантаження або для відображення безпосередньо на HTML-сторінці, як показано нижче ( посилання ):

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

Документація: http://dwij.co.in/java-base64-image-encoder


Остання ланка (dwij.co.in) розірвана (404).
Пітер Мортенсен


9

Ось два мої центи ... Java 8 містить власну реалізацію Base64 . Однак я знайшов одну трохи тривожну різницю. Для ілюстрації я наведу приклад коду:

Моя обгортка кодеку:

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

Тестовий клас:

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

ВИХІД:

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)

Зауважте, що текст, закодований Apache, містить додаткові розриви рядків (пробіли) в кінці. Тому, щоб мій кодек дав той самий результат незалежно від реалізації Base64, мені довелося зателефонувати trim()на текст закодованого Apache. У моєму випадку я просто додав вищезазначений виклик методу до мого кодека apacheDecode()таким чином:

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

Після внесення цієї зміни я очікував розпочати:

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!

ВИСНОВОК : Якщо ви хочете перейти з Apache Base64 на Java, ви повинні:

  1. Розшифруйте закодований текст за допомогою декодера Apache.
  2. Кодуйте отриманий (звичайний) текст за допомогою Java.

Якщо ви перейдете без виконання цих кроків, швидше за все, у вас виникнуть проблеми. Саме так я зробив це відкриття.


8

На Android використовуйте статичні методи утилітного класу android.util.Base64 . У посиланій документації йдеться про те, що клас Base64 був доданий на рівні 8 API ( 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));

Це найкраща відповідь, якщо ви розробляєте для Android і не можете використовувати Java 8.
Craig Brown

6

Apache Commons має гарну реалізацію Base64. Це можна зробити так само, як:

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

Ви можете знайти більш детальну інформацію про кодування base64 при кодуванні Base64 за допомогою Java та JavaScript .


Зауважте, що це передбачає, що рядок кодується у таблиці за замовчуванням
Кірбі

6

Якщо ви використовуєте Spring Framework щонайменше версії 4.1, ви можете використовувати клас org.springframework.util.Base64Utils :

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

Він делегує Base64, кодек Apache Commons Java або Java Type 8Converter Java 8, залежно від того, що є.


4

Простий приклад з Java 8:

import java.util.Base64;

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

3

У Java 7 я зашифрував цей метод

import javax.xml.bind.DatatypeConverter;

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

Працює під Java 7 і 8, але не Java 9. Гірше того , якщо ви будуєте це під Java 7 або 8 він буде будувати , і тоді ви отримаєте ClassDefNotFoundException під час виконання під Java 9.
Стівен M-він strike-


1

Я спробував із наступним фрагментом коду. Це добре спрацювало. :-)

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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.