Java 8 Java.util.Base64是sun.misc.Base64的替代品吗?

Java 8 Java.util.Base64是sun.misc.Base64的替代品吗?,java,encoding,java-8,base64,mime,Java,Encoding,Java 8,Base64,Mime,问题 Java 8Java.util.Base64MIME编码器和解码器是否是不受支持的内部Java APIsun.misc.Base64编码器和sun.misc.Base64解码器的替代品 编辑(澄清):通过插入替换项 我的意思是,我可以使用sun.misc.Base64编码器和sun.misc.Base64解码器透明地将遗留代码切换到任何现有其他客户端代码的Java 8 MIME Base64编码器/解码器 我目前的想法以及原因 根据我的调查和快速测试(见下面的代码)这应该是替代品的下降,因

问题

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

编辑(澄清):通过插入替换项 我的意思是,我可以使用
sun.misc.Base64编码器
sun.misc.Base64解码器
透明地将遗留代码切换到任何现有其他客户端代码的Java 8 MIME Base64编码器/解码器

我目前的想法以及原因

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

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

我在寻找什么

  • 确认或反驳“替换率下降”观点的权威来源;或
  • 一个反例显示了java.util.Base64与sun.misc.Base64编码器(Base64解码器)或
  • 无论你怎么想,都能肯定地回答上述问题
供参考

我的测试代码

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");
    }
}
公共类base64编码DecodingRoundTripTest{
公共静态void main(字符串[]args)引发IOException{

String test1=“~!@$%^&*()\+=``}{[]\\\:\”?>rfc1521和rfc2045之间的base64规范没有更改

所有base64实现都可以被视为彼此的替换,base64实现之间的唯一区别是:

  • 使用的字母表
  • 所提供的API(例如,一些可能只对完整的输入缓冲区执行操作,而另一些可能是有限状态机,允许您继续通过它们推送输入块,直到完成为止)
  • MIME base64字母表在RFC版本之间保持不变(它必须保持不变,否则旧的软件会损坏),它是:
    abcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyz+/

    注意,在base64实现之间,只有最后2个字符可以更改

    作为更改最后2个字符的base64实现的示例,规范使用以下base64字母表:
    abcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyz+,


    更改的原因是
    /
    字符通常用作路径分隔符,并且由于MUTF-7编码用于将非ASCII目录路径展平为ASCII,因此需要在编码段中避免使用
    /
    字符。

    假设两个编码器都没有错误,则RFC需要为eve使用不同的编码ry 0字节、1字节、2字节和3字节序列。较长的序列根据需要分解为尽可能多的3字节序列,然后是最终序列。因此,如果这两种实现正确处理所有16843009(1+256+65536+16777216)可能的序列,那么这两种实现也是相同的

    这些测试只需要几分钟就可以运行。通过稍微更改测试代码,我已经完成了这项工作,并且我的Java 8安装通过了所有测试。因此,可以使用公共实现安全地替换sun.misc实现

    以下是我的测试代码:

    import java.util.Base64;
    import java.util.Arrays;
    import java.io.IOException;
    
    public class Base64EncodingDecodingRoundTripTest {
    
        public static void main(String[] args) throws IOException {
            System.out.println("Testing zero byte encoding");
            encodeDecode(new byte[0]);
    
            System.out.println("Testing single byte encodings");
            byte[] test = new byte[1];
            for(int i=0;i<256;i++) {
                test[0] = (byte) i;
                encodeDecode(test);
            }
            System.out.println("Testing double byte encodings");
            test = new byte[2];
            for(int i=0;i<65536;i++) {
                test[0] = (byte) i;
                test[1] = (byte) (i >>> 8);
                encodeDecode(test);
            }
            System.out.println("Testing triple byte encodings");
            test = new byte[3];
            for(int i=0;i<16777216;i++) {
                test[0] = (byte) i;
                test[1] = (byte) (i >>> 8);
                test[2] = (byte) (i >>> 16);
                encodeDecode(test);
            }
            System.out.println("All tests passed");
        }
    
        static void encodeDecode(final byte[] testInput) 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(testInput);
            String mimeEncoded = mimeEncoder.encodeToString(testInput);
    
            // check encodings equal
            if( ! sunEncoded.equals(mimeEncoded) ) {
                throw new IOException("Input "+Arrays.toString(testInput)+" produced different encodings (sun=\""+sunEncoded+"\", mime=\""+mimeEncoded+"\")");
            }
    
            // Check cross decodes are equal. Note encoded forms are identical
            byte[] mimeDecoded = mimeDecoder.decode(sunEncoded);
            byte[] sunDecoded = unsupportedDecoder.decodeBuffer(mimeEncoded); // throws IOException
            if(! Arrays.equals(mimeDecoded,sunDecoded) ) {
                throw new IOException("Input "+Arrays.toString(testInput)+" was encoded as \""+sunEncoded+"\", but decoded as sun="+Arrays.toString(sunDecoded)+" and mime="+Arrays.toString(mimeDecoded));
            }
    
        }
    }
    
    import java.util.Base64;
    导入java.util.array;
    导入java.io.IOException;
    公共类Base64编码DecodingRoundTripTest{
    公共静态void main(字符串[]args)引发IOException{
    System.out.println(“测试零字节编码”);
    编码解码(新字节[0]);
    System.out.println(“测试单字节编码”);
    字节[]测试=新字节[1];
    对于(int i=0;i>8);
    编解码(测试);
    }
    System.out.println(“测试三字节编码”);
    测试=新字节[3];
    对于(int i=0;i>>8);
    测试[2]=(字节)(i>>>16);
    编解码(测试);
    }
    System.out.println(“所有测试通过”);
    }
    静态void encodecode(最终字节[]testInput)引发IOException{
    sun.misc.BASE64Encoder unsupportedEncoder=新的sun.misc.BASE64Encoder();
    sun.misc.BASE64Decoder unsupportedDecoder=新的sun.misc.BASE64Decoder();
    Base64.Encoder mimeEncoder=java.util.Base64.getMimeEncoder();
    Base64.Decoder mimeDecoder=java.util.Base64.getMimeDecoder();
    字符串suncoded=unsupportedEncoder.encode(testInput);
    字符串mimeEncoded=mimeEncoder.encodeToString(testInput);
    //检查编码是否相等
    如果(!suncoded.equals(mimeEncoded)){
    抛出新的IOException(“输入”+数组。toString(testInput)+”产生了不同的编码(sun=\”“+sunEncoded+“\”,mime=\”“+mimeEncoded+“\”);
    }
    //检查交叉解码是否相等。注意编码形式相同
    字节[]mimedecode=mimeDecoder.decode(suncoded);
    byte[]sunDecoded=unsupportedDecoder.decodeBuffer(mimeEncoded);//引发IOException
    如果(!array.equals(mimedecode,sundecode)){
    抛出新IOException(“输入”+Arrays.toString(testInput)+”编码为\“+sunEncoded+”\”,但解码为sun=“+Arrays.toString(sunDecoded)+”和mime=“+Arrays.toString(mimeDecoded));
    }
    }
    }
    
    下面是一个小测试程序,说明了编码字符串中的差异:

    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));
    
    byte[]bytes=新字节[57];
    字符串enc1=ne
    
    enc1 = <AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    >
    enc2 = <AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>
    false