我需要在Java中编码Base64编码中的一些数据。我怎么做呢?提供Base64编码器的类的名称是什么?


我试着利用太阳。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.*;

并导入从http://commons.apache.org/codec/下载的JAR文件

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


当前回答

将这个库添加到应用级依赖项中

实现“org.apache.commons: commons-collections4:4.4”

其他回答

对于Java 6-7,最好的选择是从Android存储库中借用代码。它没有依赖关系。

https://github.com/android/platform_frameworks_base/blob/master/core/java/android/util/Base64.java

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实现如何,我必须在Apache编码的文本上调用trim()。在我的例子中,我简单地将前面提到的方法调用添加到我的编解码器的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,你必须:

用Apache解码器解码已编码的文本。 用Java编码产生的(纯)文本。

如果您没有按照这些步骤进行切换,很可能会遇到问题。这就是我的发现。

Eclipse给您一个错误/警告,因为您试图使用特定于JDK供应商的内部类,而不是公共API的一部分。Jakarta Commons提供了自己的base64编解码器实现,当然这些实现位于不同的包中。删除这些导入,并让Eclipse为您导入适当的Commons类。

您需要更改类的导入:

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。使用Java 8的Base64。首先,像往常一样导入它:

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文档。

如果你坚持使用比8更早的Java版本,但已经在为Java使用AWS SDK,你可以使用com.amazonaws.util.Base64。