我有一个Base64编码的图像。Java中最好的解码方法是什么?希望只使用Sun Java 6中包含的库。


当前回答

你可以简单地试试这个。

byte[] data = Base64.getDecoder().decode(base64fileContent);

Base64. getdecode()返回一个可以解码的Base64解码器。然后你需要再次使用.decode(<your base64>)解码。

其他回答

作为sun.misc的替代品。BASE64Decoder或非核心库,请查看javax.mail.internet.MimeUtility.decode()。

public static byte[] encode(byte[] b) throws Exception {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    OutputStream b64os = MimeUtility.encode(baos, "base64");
    b64os.write(b);
    b64os.close();
    return baos.toByteArray();
}
public static byte[] decode(byte[] b) throws Exception {
    ByteArrayInputStream bais = new ByteArrayInputStream(b);
    InputStream b64is = MimeUtility.decode(bais, "base64");
    byte[] tmp = new byte[b.length];
    int n = b64is.read(tmp);
    byte[] res = new byte[n];
    System.arraycopy(tmp, 0, res, 0, n);
    return res;
}

链接与完整的代码:编码/解码到/从Base64

另一个迟来的答案,但我的基准测试表明,Jetty的Base64编码器的实现非常快。不如MiGBase64快,但比iHarder Base64快。

import org.eclipse.jetty.util.B64Code;

final String decoded = B64Code.decode(encoded, "UTF-8");

我还做了一些基准测试:

      library     |    encode    |    decode   
------------------+--------------+-------------
 'MiGBase64'      |  10146001.00 |  6426446.00
 'Jetty B64Code'  |   8846191.00 |  3101361.75
 'iHarder Base64' |   3259590.50 |  2505280.00
 'Commons-Codec'  |    241318.04 |   255179.96

这些是每秒跑数,所以越高越好。

在用Java 7编译但可能运行在更高Java版本的代码中,检测Java .util的存在似乎很有用。Base64类,并使用在这里的其他问题中提到的给定JVM的最佳方法。

我使用了下面的代码:

private static final Method JAVA_UTIL_BASE64_GETENCODER;

static {
    Method getEncoderMethod;
    try {
        final Class<?> base64Class = Class.forName("java.util.Base64");
        getEncoderMethod = base64Class.getMethod("getEncoder");
    } catch (ClassNotFoundException | NoSuchMethodException e) {
        getEncoderMethod = null;
    }
    JAVA_UTIL_BASE64_GETENCODER = getEncoderMethod;
}

static String base64EncodeToString(String s) {
    final byte[] bytes = s.getBytes(StandardCharsets.ISO_8859_1);
    if (JAVA_UTIL_BASE64_GETENCODER == null) {
        // Java 7 and older // TODO: remove this branch after switching to Java 8
        return DatatypeConverter.printBase64Binary(bytes);
    } else {
        // Java 8 and newer
        try {
            final Object encoder = JAVA_UTIL_BASE64_GETENCODER.invoke(null);
            final Class<?> encoderClass = encoder.getClass();
            final Method encodeMethod = encoderClass.getMethod("encode", byte[].class);
            final byte[] encodedBytes = (byte[]) encodeMethod.invoke(encoder, bytes);
            return new String(encodedBytes);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new IllegalStateException(e);
        }
    }
}

给出一个javax.xml.bind.DatatypeConverter的测试编码/解码示例,使用方法parseBase64Binary()和printBase64Binary()引用@jeremy-ross和@nightfirecat answer。

@Test
public void EncodeDecode() {
    //ENCODE
    String hello = "Hello World";
    byte[] helloBytes = hello.getBytes(StandardCharsets.UTF_8);
    String encodedHello = DatatypeConverter.printBase64Binary(helloBytes);
    LOGGER.info(hello + " encoded=> " + encodedHello);

    //DECODE
    byte[] encodedHelloBytes = DatatypeConverter.parseBase64Binary(encodedHello);
    String helloAgain = new String(encodedHelloBytes, StandardCharsets.UTF_8) ;
    LOGGER.info(encodedHello + " decoded=> " + helloAgain);

    Assert.assertEquals(hello, helloAgain);
}

结果:

INFO - Hello World encoded=> SGVsbG8gV29ybGQ=
INFO - SGVsbG8gV29ybGQ= decoded=> Hello World

不需要使用commons——Sun在Java中附带了base64编码器。你可以这样导入它:

import sun.misc.BASE64Decoder;

然后像这样使用它:

BASE64Decoder decoder = new BASE64Decoder();
byte[] decodedBytes = decoder.decodeBuffer(encodedBytes);

其中encodedBytes是java.lang.String或java.io.InputStream。只是要当心太阳。*类不是Sun的“官方支持”。

编辑:谁能想到这将是我发表过的最具争议的答案呢?我知道太阳。*不支持或保证软件包继续存在,我确实了解Commons并一直在使用它。然而,发帖者要求一个“包含在Sun Java 6中”的类,这就是我试图回答的问题。总的来说,我同意Commons是最好的方式。

编辑2:正如amir75在下面指出的那样,Java 6+附带了JAXB,其中包含支持的编码/解码Base64的代码。请看下面Jeremy Ross的回答。