将字符串编码为 Base36

Encode String to Base36

目前我正在研究一种算法,用于将包含每个可能字符的普通字符串编码为 Base36 字符串。

我尝试了以下方法,但没有用。

public static String encode(String str) {
    return new BigInteger(str, 16).toString(36);
}

我猜这是因为字符串不仅仅是一个十六进制字符串。如果我在 Base36 中使用字符串 "Hello22334!",那么我会得到一个 NumberFormatException.

我的方法是将每个字符转换为数字。将数字转换为十六进制表示,然后将 hexstring 转换为 Base36。

我的方法可以吗,或者有更简单或更好的方法吗?

首先,您需要将字符串转换为数字,用一组字节表示。这就是您使用编码的目的。我强烈推荐 UTF-8。

然后您需要将该数字、字节集转换为以 36 为基数的字符串。

byte[] bytes = string.getBytes(StandardCharsets.UTF_8); 
String base36 = new BigInteger(1, bytes).toString(36);

解码:

byte[] bytes = new Biginteger(base36, 36).toByteArray();
// Thanks to @Alok for pointing out the need to remove leading zeroes.
int zeroPrefixLength = zeroPrefixLength(bytes);
String string = new String(bytes, zeroPrefixLength, bytes.length-zeroPrefixLength, StandardCharsets.UTF_8));

private int zeroPrefixLength(final byte[] bytes) {
    for (int i = 0; i < bytes.length; i++) {
        if (bytes[i] != 0) {
            return i;
        }
    }
    return bytes.length;
}

从 Base 10 到 Base36

public static String toBase36(String str) {
        try {
            return Long.toString(Long.valueOf(str), 36).toUpperCase();
        } catch (NumberFormatException | NullPointerException ex) {
            ex.printStackTrace();
        }
        return null;
    }

从 Base36 字符串到 Base10

public static String fromBase36(String b36) {
        try {
            BigInteger base = new BigInteger( b36, 36);
            return base.toString(10);
        }catch (Exception e){
             e.printStackTrace();
        }
       return null;
    }