Java 8 java.util.Base64 是 sun.misc.BASE64 的直接替代品吗?

2022-09-01 00:27:40

问题

Java 8 MIME Encoder and Decoder 是否是不受支持的内部 Java API 和 ?java.util.Base64sun.misc.BASE64Encodersun.misc.BASE64Decoder

编辑(澄清):通过直接替换,我的意思是我可以使用sun.misc.BASE64Encodersun.misc.BASE64Decoder将遗留代码透明地切换到Java 8 MIME Base64 Encoder/Decoder,用于任何其他现有的客户端代码。

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

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

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

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

我要找什么

  • 确认或反驳“直接替换”点的权威来源,或
  • 一个反例,它显示了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");
    }
}

答案 1

下面是一个小测试程序,说明了编码字符串的差异:

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

其输出为:

enc1 = <AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>
enc2 = <AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>
false

请注意,编码的输出末尾有一个换行符。它并不总是追加换行符,但如果编码的字符串在其最后一行正好有76个字符,它恰好会这样做。(的作者认为这是实现中的一个小错误 - 请参阅评论线程)。sun.misc.BASE64Encoderjava.util.Base64sun.misc.BASE64Encoder

这似乎是一件微不足道的事情,但是如果您有一个依赖于此特定行为的程序,则切换编码器可能会导致输出格式不正确。因此,我的结论是,这不是 的直接替代品。java.util.Base64sun.misc.BASE64Encoder

当然,其目的是它是功能等效的,符合RFC的,高性能的,完全支持和指定的替换,旨在支持将代码从.但是,在迁移时,您需要注意一些这样的边缘情况。java.util.Base64sun.misc.BASE64Encoder


答案 2

我有同样的问题,当我从 移动到 时,但后来解决了我的问题sunjava.util.base64org.apache.commons.codec.binary.Base64


推荐