Base128 使用 128 個可列印字元,每字元承載 7 bits,比 Base64 (6 bits) 更緊湊。本文提供一個 MyBASE128 類別,支援自訂符號表、編碼/解碼、單元測試。
import java.util.*;
public class Base128Codec {
private static final char[] ENCODE_TABLE = new char[128];
private static final Map DECODE_MAP = new HashMap<>(128);
static {
int idx = 0;
// 先放入字母數字
for (char c = 'A'; c <= 'Z'; c++) ENCODE_TABLE[idx++] = c;
for (char c = 'a'; c <= 'z'; c++) ENCODE_TABLE[idx++] = c;
for (char c = '0'; c <= '9'; c++) ENCODE_TABLE[idx++] = c;
// 再補入自訂符號(確保不重複)
String extra = "這是自訂符號表!@#$%^&*()_+-=[]{}|;:,.<>?";
for (char c : extra.toCharArray()) {
if (idx >= 128) break;
if (DECODE_MAP.containsKey(c)) continue;
ENCODE_TABLE[idx++] = c;
}
if (idx != 128) throw new IllegalStateException("符號表長度不足 128");
for (int i = 0; i < 128; i++) DECODE_MAP.put(ENCODE_TABLE[i], i);
}
public static String encode(byte[] data) {
if (data == null || data.length == 0) return "";
StringBuilder sb = new StringBuilder();
int tail = 0;
for (int i = 0; i < data.length; i++) {
int mov = (i % 7) + 1;
int curr = data[i] & 0xFF;
int code = tail | (curr >> mov);
sb.append(ENCODE_TABLE[code]);
tail = (curr << (8 - mov)) & 0x7F;
if (mov == 7) {
sb.append(ENCODE_TABLE[tail]);
tail = 0;
}
}
sb.append(ENCODE_TABLE[tail]);
return sb.toString();
}
public static byte[] decode(String str) {
if (str == null || str.isEmpty()) return new byte[0];
int n = (int) Math.floor(str.length() * 7.0 / 8);
byte[] out = new byte[n];
int idx = 0;
int head = DECODE_MAP.get(str.charAt(0)) << 1;
for (int i = 1; i < str.length(); ) {
int mod = i % 8;
int code = DECODE_MAP.get(str.charAt(i++));
out[idx++] = (byte) ((head | (code >> (7 - mod))) & 0xFF);
if (mod == 7) {
head = DECODE_MAP.get(str.charAt(i++)) << 1;
} else {
head = (code << (mod + 1)) & 0xFF;
}
}
return out;
}
public static void main(String[] args) {
String test = "Hello Base128 中文測試";
String enc = encode(test.getBytes());
System.out.println("Encoded: " + enc);
System.out.println("Decoded: " + new String(decode(enc)));
}
}