Кодирование как Base64 в Java


317

Мне нужно закодировать некоторые данные в кодировке Base64 в Java. Как я могу это сделать? Как называется класс, предоставляющий кодировщик Base64?


Я пытался использовать sun.misc.BASE64Encoderкласс, но безуспешно. У меня есть следующая строка кода Java 7:

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

Я использую Затмение. Eclipse помечает эту строку как ошибку. Я импортировал необходимые библиотеки:

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

Но опять же, оба они показаны как ошибки. я нашел похожий пост здесь .

Я использовал Apache Commons в качестве решения, включающего:

import org.apache.commons.*;

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

Но проблема все еще существует. Затмение по-прежнему показывает ошибки, упомянутые ранее. Что я должен делать?


7
Мой совет: прочитайте сообщение об ошибке и попытайтесь понять, что оно говорит.
Дж. Б. Низет

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
наушники

Ответы:


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

Затем прочитайте, почему вы не должны использовать пакеты sun. * .


Обновление (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
pratnala

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

@Frank Декодирование байтов сразу вызывает ошибку OutOfMemory. Любая идея обработать это в буфере
xyz

225

Используйте класс Java 8 «никогда не поздно присоединиться к веселью»: java.util.Base64

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

11
Хотя это тривиальный комментарий, обратите внимание, что если вы используете его, вы не совместимы со старыми версиями Java, которые (по крайней мере, на данный момент), вероятно, гораздо более распространены.
кодер

Я бы также выбрал класс 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 предоставляет собственную реализацию кодеков base64, которые, конечно, находятся в другом пакете. Удалите этот импорт и позвольте Eclipse импортировать соответствующую классу Commons для вас.


Не проект Jakarta уже не . Он был смешан и сопоставлен (и имя повторно используется для 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 был добавлен в 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));

Это лучший ответ, если вы разрабатываете для Android, и вы не можете использовать Java 8.
Крейг Браун

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 .


Обратите внимание, что предполагается, что строка закодирована в кодировке по умолчанию
Kirby

6

Если вы используете Spring Framework как минимум версии 4.1, вы можете использовать класс org.springframework.util.Base64Utils :

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

Он будет делегировать Java 8 Base64, Apache Commons Codec или JAXB DatatypeConverter, в зависимости от того, что доступно.


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.
Стивен М - на забастовку -


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.