有没有一个适用于Android和Java的Base64库?

11

我有一个常用的库,可以在Java和Android项目中使用,它需要一个base64编码器/解码器。问题是,Apache commons库不适用于Android,至少我无法成功地实现它——由于Android已经实现了早期版本,每当我尝试编码或解码时就会在运行时引发错误:

Base64.decodeBase64
返回错误:
AndroidRuntime(1420): java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Base64.decodeBase64

如果有人知道一个既与Java又与Android兼容的base64库,或者能够向我解释如何解决Apache commons问题,我将非常感激。 :^)


你确定你没有包含Apache Commons Codec库吗?这个方法已经存在多年了。 - Sean Owen
是的,我已经包含了它。在使用Android 5或更高版本时存在冲突。在版本5之前不存在这些方法 - 据我所知,Android正在使用版本4。 - Roy Hinkley
如果你不相信我,那就自己试试,证明我错了。使用Apache commons v1.7,我得到了以下错误 --> AndroidRuntime(1420): java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Base64.decodeBase64 - Roy Hinkley
拜托了,就像webnet所说的那样,学习简单的算法并自己编写代码。你甚至可以用Javascript来写。 - Blessed Geek
那么为什么你不能使用在4中存在的方法呢? - user207421
Guava将在14.0版本中推出,尽管目前还未发布。 - Louis Wasserman
3个回答

11

只需要使用"base64"。这个问题很简单,你可以谷歌搜索任何“Java base64”并使用任何实现。

编辑

如果您的目标是API8之前的版本,只需从API8的Base64实现中获取源代码(它在android/util/Base64.java)中复制到您的项目中即可。


如果我可以使用任何实现,那么Apache Commons就可以工作,sun.misc.BASE64Decoder也可以,但它们都不行。我只想要来自可信来源的库。 - Roy Hinkley
2
所以只需使用Android源代码并将其放入您的项目中。我在我的编辑答案中添加了链接。 - Marcin Orlowski
同意WebnetMobile.com的观点,从Android源代码中复制Base64.java并将其放入您的项目中。 - Win Myo Htet
1
如果您有一个依赖于Base64类的库,那么您可能需要分叉该库并更新引用。很有可能它正在尝试导入foo.bar.Base64,而您却有com.yourapplication.util.Base64 - twaddington
好的,我已经让源代码在Android上运行,并正在验证我的J2EE应用程序。如果它能正常工作,我会将其标记为答案。如果它能正常工作,非常感谢! - Roy Hinkley

2

自己动手,丰衣足食。

这是解码:

      static private int FromBase64Char(int c)
{
    if(c >= 'A' && c <= 'Z')
        return c - 'A';
    else if(c >= 'a' && c <= 'z')
        return c - 'a' + 26;
    else if(c >= '0' && c <= '9')
        return c - '0' + 52;
    else if(c == '+')
        return 62;
    else if(c == '/')
        return 63;
    else
        throw new IllegalArgumentException(); //Depends on how do you want to handle invalid characters
}


static public byte[] FromBase64(String s) throws IllegalArgumentException
{
    if(s == null)
        return null;

    int l = s.length();
    if(l == 0)
        return new byte[0];

    if(l % 4 != 0)
        throw new IllegalArgumentException();

    boolean Padded = (s.charAt(l-1) == '=');
    boolean Padded2 = (s.charAt(l-2) == '=');
    int ll = (Padded ? l-4 : l);
    int triad;

    byte [] b = new byte[(ll*3)/4 + (Padded ? (Padded2 ? 1 : 2) : 0)];

    int i, j = 0;
    for(i=0; i<ll; i+=4)
    {
        triad = 
            (FromBase64Char(s.charAt(i)) << 18) |
            (FromBase64Char(s.charAt(i+1)) << 12) |
            (FromBase64Char(s.charAt(i+2)) << 6) |
            FromBase64Char(s.charAt(i+3));

        b[j++] = (byte)((triad >> 16) & 0xff); 
        b[j++] = (byte)((triad >> 8) & 0xff);
        b[j++] = (byte)(triad & 0xff);
    }
    //The final chunk
    if(Padded)
    {
        if(Padded2) //Padded with two ='s
        {
            triad = (FromBase64Char(s.charAt(ll)) <<2 ) | (FromBase64Char(s.charAt(ll+1)) >> 4);
            b[j++] = (byte)triad;
        }
        else //Padded with one =
        {
            triad =
                (FromBase64Char(s.charAt(ll)) << 10) |
                (FromBase64Char(s.charAt(ll+1)) << 4) |
                (FromBase64Char(s.charAt(ll+2)) >> 2);  
            b[j++] = (byte)((triad >> 8) & 0xff);
            b[j++] = (byte)(triad & 0xff);
        }
    }
    return b;
}

这里是编码:

private final static String BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
        PAD1 = "=", PAD2 = "==";

static public String ToBase64(final byte [] a)
{
    int l = a.length;
    StringBuilder sb = new StringBuilder((l+3)*4/3);
    int i;
    int mod = l % 3;
    int ll = l - mod;
    int triad;
    for(i=0;i<ll;i+=3)
    {
        triad = (a[i]<<16) | (a[i+1]<<8) | a[i+2];
        sb.append(BASE64_ALPHABET.charAt((triad >> 18) & 0x3f));
        sb.append(BASE64_ALPHABET.charAt((triad >> 12) & 0x3f));
        sb.append(BASE64_ALPHABET.charAt((triad >> 6) & 0x3f));
        sb.append(BASE64_ALPHABET.charAt(triad & 0x3f));
    }
    if(mod == 1)
    {
        sb.append(BASE64_ALPHABET.charAt((a[i] >> 2) & 0x3f));
        sb.append(BASE64_ALPHABET.charAt((a[i] << 4) & 0x3f));
        sb.append(PAD2);
    }
    if(mod == 2)
    {
        triad = (a[i]<<8) | a[i+1];
        sb.append(BASE64_ALPHABET.charAt((triad >> 10) & 0x3ff));
        sb.append(BASE64_ALPHABET.charAt((triad >> 4) & 0x3f));
        sb.append(BASE64_ALPHABET.charAt((triad << 2) & 0x3f));
        sb.append(PAD1);        
    }
    return sb.toString();   
}

我尝试了这个,但在解码时出现了错误。错误是javax.crypto.BadPaddingException。 - Roy Hinkley
这段代码没有抛出BadPaddingException异常,只有IllegalArgumentException异常。一定是其他原因。 - Seva Alekseyev

0
在我的应用程序中,我使用Jackson并且它提供了一个base64编码器/解码器,如果你的应用程序也使用Jackson,你可以使用它。
import com.fasterxml.jackson.core.Base64Variants;

public class Foo {
    String encodeBase64(byte[] string) {
        return Base64Variants.getDefaultVariant().encode(string.getBytes());
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接