Кодирование как 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==
Kirby
источник
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));
stinepike
источник
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.

Если вы переключитесь без выполнения этих шагов, скорее всего у вас возникнут проблемы. Вот как я сделал это открытие.

hfontanez
источник
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 .

faisalbhagat
источник
Обратите внимание, что предполагается, что строка закодирована в кодировке по умолчанию
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, в зависимости от того, что доступно.

holmis83
источник
4

Простой пример с Java 8:

import java.util.Base64;

String str = "your string";
String encodedStr = Base64.getEncoder().encodeToString(str.getBytes("utf-8"));
z3d0
источник
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");
TMH
источник
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;
}
гандур абделькрим
источник