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

问题

Java 8 java.util.Base64 MIME编码器和解码器是否可以代替不受支持的内部Java API sun.misc.BASE64Encodersun.misc.BASE64Decoder替代

我到目前为止的想法以及的原因

根据我的调查和快速测试(请参见下面的代码),应该将其替换为,因为

基于其JavaDoc的

  • sun.misc.BASE64Encoder RFC1521 中指定的BASE64字符编码器。该RFC是 MIME 规范的一部分...
  • 基于其JavaDoc的java.util.Base64使用 RFC 2045 表1中指定的“Base64字母”进行编码和解码操作... 下MIME
  • 假设RFC 1521和2045中没有重大变化(我找不到任何变化),并且基于使用Java 8 Base64 MIME编码器/解码器的快速测试,应该可以。

    我在寻找什么

  • 权威来源,用于确认或否定“直接替换”点或
  • 是一个反例,它显示java.util.Base64与sun.misc.BASE64Encoder行为不同的情况OpenJDK Java 8 implementation (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");
        }
    }
    

    参考方案

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

    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
    

    请注意,sun.misc.BASE64Encoder的编码输出在末尾有换行符。它并不总是附加一个换行符,但是如果编码的字符串的最后一行恰好有76个字符,它就会这样做。 (java.util.Base64的作者认为这是sun.misc.BASE64Encoder实现中的一个小错误-参见review thread)。

    这看似微不足道,但是如果您有一个依赖于此特定行为的程序,则切换编码器可能会导致输出格式错误。因此,我得出的结论是java.util.Base64而不是替代sun.misc.BASE64Encoder

    当然,java.util.Base64的意图是它是功能上等效的,符合RFC的高性能,完全受支持的指定替换,旨在支持从sun.misc.BASE64Encoder迁移代码。但是,您在迁移时需要注意一些这样的极端情况。

    使用java.util.properties存储ArrayList和HashMap - java

    如何使用ArrayList存储HashMap和/或java.util.properties变量?如果不可能,可以使用其他什么类来存储应用程序配置? 参考方案 如果只需要将集合序列化为字符串,我强烈建议XStream。它使用反射将类序列化为XML。如果默认行为对您要序列化的类不起作用,则有文档,但是到目前为止,以下内容对我而言一直有效:XStream xstr…

    Java将oracle时间戳解析为date.util.date - java

    我想将oracle时间戳(01-MAY-12 01.00.47.000000000 PM)解析为java.util.Date我用这个:Date dateStart=new SimpleDateFormat("yy-MM-dd HH:mm:ss.S").parse("01-MAY-12 01.00.47.000000000 PM&…

    Java:线程池如何将线程映射到可运行对象 - java

    试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

    java.util.Scanner不返回到提示 - java

    import java.util.Scanner; class newClass { public static void main(String args[]) { Scanner s = new Scanner(System.in); while (s.hasNext()) { System.out.println(s.next()); } s.clos…

    java.util.HashSet是否不遵循其规范? - java

    作为相对的Java noob,我很困惑地发现以下内容:Point.java:public class Point { ... public boolean equals(Point other) { return x == other.x && y == other.y; } ... } Edge.java:public class Edge…