从sun.misc.BASE64迁移到Java 8 java.util.Base64

Ivo*_*ori 30 java base64 encoding mime java-8

是Java 8 java.util.Base64MIME编码器和解码器一个下拉更换为不支持的,内部的Java API sun.misc.BASE64Encodersun.misc.BASE64Decoder

到目前为止我的想法和原因

根据我的调查和快速测试(见下面的代码),它应该是替代品,因为

  • sun.misc.BASE64Encoder基于其JavaDoc是RFC1521中规定的BASE64字符编码器.此RFC是MIME规范的一部分......
  • java.util.Base64基于JavaDoc 使用RFC 2045表1中指定的"Base64 Alphabet" 进行编码和解码操作...MIME下

假设RFC 1521和2045没有重大变化(我找不到任何变化)并且基于我使用Java 8 Base64 MIME编码器/解码器的快速测试应该没问题.

我在找什么

  • 确认或反驳"直接替换"点OR的权威来源
  • 一个反例,显示了java.util.Base64具有与sun.misc.BASE64Encoder OpenJDK Java 8实现(8u40-b25)(BASE64Decoder)不同的行为的情况
  • 你认为无论如何回答上述问题肯定

以供参考

我的测试代码

public class Base64EncodingDecodingRoundTripTest {

    public static void main(String[] args) throws IOException {
        String test1 = " ~!@#$%^& *()_+=`| }{[]\\;: \"?><,./ ";
        String test2 = test1 + test1;

        encodeDecode(test1);
        encodeDecode(test2);
    }

    static void encodeDecode(final String testInputString) throws IOException {
        sun.misc.BASE64Encoder unsupportedEncoder = new sun.misc.BASE64Encoder();
        sun.misc.BASE64Decoder unsupportedDecoder = new sun.misc.BASE64Decoder();

        Base64.Encoder mimeEncoder = java.util.Base64.getMimeEncoder();
        Base64.Decoder mimeDecoder = java.util.Base64.getMimeDecoder();

        String sunEncoded = unsupportedEncoder.encode(testInputString.getBytes());
        System.out.println("sun.misc encoded: " + sunEncoded);

        String mimeEncoded = mimeEncoder.encodeToString(testInputString.getBytes());
        System.out.println("Java 8 Base64 MIME encoded: " + mimeEncoded);

        byte[] mimeDecoded = mimeDecoder.decode(sunEncoded);
        String mimeDecodedString = new String(mimeDecoded, Charset.forName("UTF-8"));

        byte[] sunDecoded = unsupportedDecoder.decodeBuffer(mimeEncoded); // throws IOException
        String sunDecodedString = new String(sunDecoded, Charset.forName("UTF-8"));

        System.out.println(String.format("sun.misc decoded: %s | Java 8 Base64 decoded:  %s", sunDecodedString, mimeDecodedString));

        System.out.println("Decoded results are both equal: " + Objects.equals(sunDecodedString, mimeDecodedString));
        System.out.println("Mime decoded result is equal to test input string: " + Objects.equals(testInputString, mimeDecodedString));
        System.out.println("\n");
    }
}
Run Code Online (Sandbox Code Playgroud)

Stu*_*rks 51

这是一个小型测试程序,用于说明编码字符串的不同之处:

byte[] bytes = new byte[57];
String enc1 = new sun.misc.BASE64Encoder().encode(bytes);
String enc2 = new String(java.util.Base64.getMimeEncoder().encode(bytes),
                         StandardCharsets.UTF_8);

System.out.println("enc1 = <" + enc1 + ">");
System.out.println("enc2 = <" + enc2 + ">");
System.out.println(enc1.equals(enc2));
Run Code Online (Sandbox Code Playgroud)

它的输出是:

enc1 = <AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>
enc2 = <AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>
false
Run Code Online (Sandbox Code Playgroud)

请注意,编码输出最后sun.misc.BASE64Encoder有一个换行符.它并不总是附加换行符,但如果编码的字符串在其最后一行上恰好包含76个字符,则会发生这种情况.(作者java.util.Base64认为这是实现中的一个小错误sun.misc.BASE64Encoder- 请参阅审核主题).

这可能看起来很简单,但是如果你有一个依赖于这种特定行为的程序,切换编码器可能会导致输出格式错误.因此,我的结论java.util.Base64是,这不是替代品sun.misc.BASE64Encoder.

当然,意图java.util.Base64是,它是一个功能上等同,RFC-符合性,高性能,完全支持并指定了一种旨在支持的代码迁移远离更换sun.misc.BASE64Encoder.但是,在迁移时,您需要注意这种边缘情况.

  • _Perfect_,您找到了一个反例! (2认同)
  • @IvoMori我可能还有些其他情况,我不知道还有其他情况。我怀疑它们会被记录在案。这个问题(通常适用于sun.misc)是因为它从未被正式指定,并且没有像Java。* API那样的一致性和回归测试套件。“ sun.misc.BASE64”东西只是“完成了它的工作”的一大堆代码,因此很可能甚至有可能出现奇特的边缘行为,甚至隐匿着错误。 (2认同)

use*_*151 6

我有同样的问题,当我从sun移到 时java.util.base64,但后来org.apache.commons.codec.binary.Base64解决了我的问题