在Java中编码为Base64


317

我需要使用Java中的Base64编码对一些数据进行编码。我怎么做?提供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/

但是问题仍然存在。Eclipse仍然显示前面提到的错误。我该怎么办?


7
我的建议:阅读错误消息,并尝试理解错误消息。
JB Nizet 2012年

27
你不应该下使用类sun.**
onon15

16
它们不属于公共API;它们可能会被更改,删除或任何其他形式,恕不另行通知。其中一些可能是实验性的,或者不是生产级的。 oracle.com/technetwork/java/faq-sun-packages-142232.html
onon15 2012年

5
使用 Java 6及更高版本中随附的JAXB DatatypeConverter
伊恩·罗伯茨

9
java.util.Base64在Java 8 可用
earcam

Answers:


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,您可以使用Java8。首先,像平常一样导入它:

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

有关更多信息,请参见Base64的Java文档


我需要下载任何外部软件包才能正常工作吗?如果是的话,哪个?
2014年

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的旧版本(至少在当前时间点上)可能更为流行。
编码器2014年

我也会选择Java 8的类是可能的。我目前正在上一堂课,从我们的春季项目中删除apache commons库。大部分内容都可以轻松地用Spring库或jdk中的方法替换。
Adrian Cosma

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 2014年

9
最后,从Java 8中的Base64类将是走的方式。但是,如果同时要针对Java 7,则此解决方案很好,因为它不依赖外部库。
dana

4
这确实不是Java 9更糟下工作,编译为Java 7的代码中使用的javax.xml.bind *会在运行时失败的Java下9.。
斯蒂芬·中号-on透湿

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)。您可以更新答案并提供一些参考吗?例如,现在上课Base64org.apache.commons.codec.binary吗?现在是针对这种情况的Apache Commons吗?
彼得·莫滕森

9

要进行此转换,您需要一个编码器和解码器,该编码器和解码器将从Base64Coder(Java中的开源Base64编码器/解码器)中获取。这是您需要的文件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,以上传到服务器或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”是图像的文本表示。您可以将其用于上传目的或直接显示到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));

您可以在使用Java和JavaScript的Base64编码中找到有关base64编码的更多详细信息。


请注意,这假设字符串是使用默认字符集编码的
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它将建造,然后你会的Java 9.下,在运行时获得ClassDefNotFoundException下工作
斯蒂芬·中号-on透湿


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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.