Codificação como Base64 em Java

317

Eu preciso codificar alguns dados na codificação Base64 em Java. Como faço isso? Qual é o nome da classe que fornece um codificador Base64?


Eu tentei usar a sun.misc.BASE64Encoderclasse, sem sucesso. Eu tenho a seguinte linha de código Java 7:

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

Estou usando o Eclipse. O Eclipse marca essa linha como um erro. Importei as bibliotecas necessárias:

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

Mas, novamente, os dois são mostrados como erros. Encontrei um post semelhante aqui .

Usei o Apache Commons como a solução sugerida, incluindo:

import org.apache.commons.*;

e importando os arquivos JAR baixados de: http://commons.apache.org/codec/

Mas o problema ainda existe. O Eclipse ainda mostra os erros mencionados anteriormente. O que devo fazer?

Júri A
fonte
7
Meu conselho: leia a mensagem de erro e tente entender o que diz.
JB Nizet 28/10/12
27
Você não é suposto classes de uso sobsun.**
onon15
16
Eles não fazem parte da API pública; eles podem ser alterados, removidos ou o que for, sem aviso prévio. Alguns deles podem ser experimentais ou simplesmente não de nível de produção. oracle.com/technetwork/java/faq-sun-packages-142232.html
onon15
5
Ou use o JAXB DatatypeConverter que está incluído como padrão no Java 6 e posterior.
11263 Ian Roberts
9
java.util.Base64 está disponível no Java 8
earcam

Respostas:

621

Você precisa alterar a importação da sua classe:

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

E altere sua classe para usar a classe Base64.

Aqui está um exemplo de código:

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

Depois leia por que você não deve usar os pacotes sun. * .


Atualização (16-12-2016)

Agora você pode usar o java.util.Base64Java 8. Primeiro, importe-o normalmente:

import java.util.Base64;

Em seguida, use os métodos estáticos Base64 da seguinte maneira:

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

Se você desejar codificar diretamente a string e obter o resultado como string codificada, poderá usar este:

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

Consulte a documentação Java para Base64 para obter mais.

Frank
fonte
Preciso baixar algum pacote externo para que isso funcione? Se sim, qual?
cancelado
2
Não, você não precisa baixar nada afaik
pratnala
16
org.apache.commons.codec.binary.Base64 não parece uma biblioteca padrão. Eu acho que você precisa incluir o apache commons para isso. Certo?
Robert Reiz 28/09
@Frank descodificar os bytes ao mesmo tempo aumento processo ideia OutOfMemory error.Any-lo em tampão
xyz
225

Use a classe nunca é tarde demais para se juntar à diversão: java.util.Base64

new String(Base64.getEncoder().encode(bytes));
bratan
fonte
11
Embora seja um comentário trivial, observe que, se você usar, não é compatível com versões mais antigas do Java, que são (pelo menos nesse momento) provavelmente muito mais prevalentes.
Dcoder 5/07
Eu também escolheria a classe do Java 8 é possível. Atualmente, estou trabalhando em uma classe para remover a biblioteca apache commons do nosso projeto de primavera. A maioria das coisas pode ser substituída facilmente pelo método das bibliotecas Spring ou jdk.
Adrian Cosma
68

No Java 8, isso pode ser feito como: Base64.getEncoder (). EncodeToString (string.getBytes (StandardCharsets.UTF_8))

Aqui está um exemplo completo curto e independente:

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

Resultado:

old crow medicine show => b2xkIGNyb3cgbWVkaWNpbmUgc2hvdw==
Kirby
fonte
3
Por que não existem constantes Charset na biblioteca padrão Java, oh por quê ?!
Lukasz Wiktor
4
Boa pergunta, Lukasz! Na verdade existem. Eu esqueci! java.nio.charset.StandardCharsets. Vou editar minha resposta. Veja stackoverflow.com/questions/1684040/…
Kirby
67

Você também pode converter usando a codificação Base64. Para fazer isso, você pode usar o javax.xml.bind.DatatypeConverter#printBase64Binarymétodo

Por exemplo:

byte[] salt = new byte[] { 50, 111, 8, 53, 86, 35, -19, -47 };
System.out.println(DatatypeConverter.printBase64Binary(salt));
stinepike
fonte
4
Enquanto isso funciona, a documentação afirma especificamente: DatatypeConverterInterface é apenas para uso do provedor JAXB.
Gbirgsbärbel
11
Eu acho que o @gebirgsbaerbel está errado, o método printX () e parseX () pode ser usado por qualquer um, a única coisa que é apenas para JAXB é o setDatatypeConverter()método (que deve ser chamado pelos provedores JAXB).
PhoneixS
9
Eventualmente, a classe Base64 do Java 8 será o caminho a percorrer. Porém, se você precisar direcionar o Java 7, entretanto, essa solução é boa, pois não depende de bibliotecas externas.
quer
4
Isso não funciona no Java 9. Pior ainda, o código compilado para o Java 7 usando javax.xml.bind. *
Falhará
21

O Google Guava é outra opção para codificar e decodificar dados Base64:

Configuração POM:

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

Código de amostra:

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

O Eclipse fornece um erro / aviso porque você está tentando usar classes internas específicas de um fornecedor JDK e não fazem parte da API pública. O Jakarta Commons fornece sua própria implementação de codecs base64, que obviamente residem em um pacote diferente. Exclua essas importações e deixe o Eclipse importar as classes apropriadas do Commons para você.

Marko Topolnik
fonte
O projeto de Jacarta não é mais . Foi misturado e correspondido (e o nome reutilizado para Java EE ). Você pode atualizar sua resposta e fornecer algumas referências? Por exemplo, agora está na classeBase64org.apache.commons.codec.binary ? Agora é o Apache Commons para este contexto?
Peter Mortensen
9

Para converter isso, você precisa de um codificador e decodificador que você obterá do Base64Coder - um codificador / decodificador Base64 de código aberto em Java . É o arquivo Base64Coder.java que você precisará.

Agora, para acessar esta classe conforme sua exigência, você precisará da classe abaixo:

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

No Android, você pode converter seu bitmap em Base64 para fazer upload em um servidor ou serviço da web.

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

Esta "encodedImage" é uma representação de texto da sua imagem. Você pode usar isso para fins de upload ou para exibir diretamente em uma página HTML, como abaixo ( referência ):

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

Documentação: http://dwij.co.in/java-base64-image-encoder

Desenvolvedor Web em Pune
fonte
O último link (dwij.co.in) está quebrado (404).
Peter Mortensen
9

Aqui estão meus dois centavos ... O Java 8 contém sua própria implementação do Base64 . No entanto, encontrei uma diferença um pouco perturbadora. Para ilustrar, fornecerei um exemplo de código:

Meu invólucro de codec:

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

Classe de teste:

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

RESULTADO:

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)

Observe que o texto codificado do Apache contém quebras de linha adicionais (espaços em branco) no final. Portanto, para que meu codec produza o mesmo resultado, independentemente da implementação do Base64, tive que chamar trim()o texto codificado do Apache. No meu caso, simplesmente adicionei a chamada de método acima mencionada ao meu codec, da apacheDecode()seguinte maneira:

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

Depois que essa alteração foi feita, os resultados são o que eu esperava começar:

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!

CONCLUSÃO : Se você deseja alternar do Apache Base64 para Java, deve:

  1. Decodifique o texto codificado com seu decodificador Apache.
  2. Codifique o texto resultante (simples) com Java.

Se você alternar sem seguir estas etapas, provavelmente terá problemas. Foi assim que fiz essa descoberta.

hfontanez
fonte
8

No Android, use os métodos estáticos da classe de utilitário android.util.Base64 . A documentação referenciada diz que a classe Base64 foi adicionada no nível 8 da 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));
Yojimbo
fonte
Esta é a melhor resposta se você está desenvolvendo para Android e você não pode usar Java 8.
Craig Brown
6

O Apache Commons possui uma boa implementação do Base64. Você pode fazer isso simplesmente como:

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

Você pode encontrar mais detalhes sobre a codificação base64 na codificação Base64 usando Java e JavaScript .

faisalbhagat
fonte
Observe que isso pressupõe que a string está codificada no conjunto de caracteres padrão
Kirby
6

Se você estiver usando o Spring Framework pelo menos na versão 4.1, poderá usar a classe org.springframework.util.Base64Utils :

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

Ele delegará no Base64, no Apache Commons Codec ou no JAXB DatatypeConverter do Java 8, dependendo do que estiver disponível.

holmis83
fonte
4

Exemplo simples com Java 8:

import java.util.Base64;

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

No Java 7, eu codifiquei esse método

import javax.xml.bind.DatatypeConverter;

public static String toBase64(String data) {
    return DatatypeConverter.printBase64Binary(data.getBytes());
}
Daniel De León
fonte
Funciona no Java 7 e 8, mas não no Java 9. Pior ainda, se você criar isso no Java 7 ou 8, ele criará e você receberá uma ClassDefNotFoundException em tempo de execução no Java 9.
Stephen M -on strike -
1

Eu tentei com o seguinte trecho de código. Funcionou bem. :-)

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