package base64;
import java.util.Arrays;
import java.util.LinkedList;
/**
* Created by Eclipse.
* 类功能描述:字符自定义编码
* 创建日期: 2008-7-23
* 创建时间: 下午05:17:10
*/
public class BaseTest {
private static final char[] alphabet = "abcdefghijklmnopqrstuvwxyz2345678".toCharArray(); //只需32位字符长度
private static final int[] codes = new int[256];
static{
Arrays.fill(codes, -1);
for (int i = 0; i < alphabet.length; i++) {
codes[alphabet[i]] = i;
}
}
public static void main(String[] args) {
String s = "bs适当モ《方#ぞラ︼Ж┷式来d的ǎΘà的⒐萨芬了?.,<>";
String a = new String(myEncode(s.getBytes()));
String b = new String(myDecode(a.getBytes()));
System.out.println(a);
System.out.println(b);
}
/**
* 解码
* @param data
* @return
*/
public static final byte[] myDecode(byte[] data){
int sLen = data != null ? data.length : 0;
if (sLen == 0)
return new byte[0];
//去除无效字符
int sepCnt = 0;
for (int i = 0; i < sLen; i++)
if (codes[data[i] & 0xFF] < 0)
sepCnt++;
int len = (sLen - sepCnt) * 5 / 8;
byte[] dArr = new byte[len];
int shift = 0;
//总和
int accum = 0;
//数组下标ID
int d = 0;
//一个一个的解
for (int i = 0; i < data.length; i++) {
int c = codes[data[i] & 0xFF];
if(c >= 0){
accum <<= 5;
shift += 5;
accum |= c;
if (shift >= 8){
shift -= 8;
dArr[d++] = (byte) ((accum >> shift) & 0xff);
}
}
}
return dArr;
}
/**
* 编码
* @param data
* @return
*/
public static final char[] myEncode(byte[] data){
int sLen = data != null ? data.length : 0;
if (sLen == 0)
return new char[0];
//一个字符八个字节,编码时每五个字符转换八个字符
char[] out = new char[(int)Math.ceil((data.length * 8) / 5.0)];
int k = 0;
for (int i = 0; i < data.length; i += 5) {
long val = (0xFF & (int) data[i]);
val <<= 8;
if((i + 1) < data.length){
val |= (0xFF & (int) data[i + 1]);
}
val <<= 8;
if((i + 2) < data.length){
val |= (0xFF & (int) data[i + 2]);
}
val <<= 8;
if((i + 3) < data.length){
val |= (0xFF & (int) data[i + 3]);
}
val <<= 8;
if((i + 4) < data.length){
val |= (0xFF & (int) data[i + 4]);
}
long temp = 0;
boolean isFirst = false;
LinkedList<Character> l = new LinkedList<Character>();
for (int j = 0; j < 8; j++) {
if((i+5)<data.length){
l.add(alphabet[(int) (val & 0x1F)]);
}
else{
temp = val & 0x1F;
if(isFirst){
l.add(alphabet[(int) temp]);
}
else if(temp!=0){
l.add(alphabet[(int) temp]);
isFirst = true;
}
}
val >>= 5;
}
//填充数组
for (int j = l.size()-1; j >= 0; j--) {
out[k] = l.get(j);
k++;
}
//填充剩余元素
if((i+5)>=data.length&&k<out.length){
for (int j = k; j < out.length; j++) {
out[j] = alphabet[0];
}
}
}
return out;
}
}
//下面摘抄别人的,注释很详细,但稍作了修改为JAVA运行程序
package base64;
/**
*/
public class Base32 {
private static String BASE32STRING = "abcdefghijklmnopqrstuvwxyz234567";
private static char[] BASE32 = BASE32STRING.toCharArray();
// 挂表,通过 BASE32[i] 和 BASE32.IndexOf(c) 获取某数字代表的字符和某字符代表的数字
public static String ToBase32(byte[] value) {
// 编码
int length = (value.length * 8 + 4) / 5;
// 计算字符串的长度,每个 byte 为8位二进制数,1到5位二进制数需要1个字符,6到10位为2个,依此类推
StringBuilder sb = new StringBuilder(length);
// 通过 StringBuilder 预先分配空间,提高效率
int cur_i = 0;
// 当前 byte[] 索引
byte cur_b = 0;
// 当前 byte
int index;
// 5位二进制数结果
int k;
// 当前二进制位索引
for (int i = 0; i < length; i++) {
// 对每个 Base32 字符循环
index = 0;
// 初始置 0
for (int j = 0; j < 5; j++) {
// 对每个 Base32 字符代表的二进制位循环
k = i * 5 + j;
// 计算当前二进制位索引
if (k == value.length * 8)
break;
// 二进制位扫描结束
if (k % 8 == 0)
cur_b = value[cur_i++];
// 转移到下一个 byte,初始化时转移到第 0 个 byte
index <<= 1;
// 左移一位以便继续设置最低位
index |= (cur_b & 128) == 0 ? 0 : 1;
// 将 byte 的最高位送入 index 的最低位
cur_b <<= 1;
// 将 byte 左移一位以将次高位变为最高位
}
sb.append(BASE32[index]);
// 追加字符
}
return sb.toString();
}
public static byte[] ToBytes(String value) {
// 解码
value = value.toLowerCase();
// 转换为小写
int length = value.length() * 5 / 8;
// 计算长度,因为末位可能会多表示 0 到 4 个二进制位,因此无需修正余数。
byte[] r = new byte[length];
// 分配空间
int cur_i = 0;
// 当前 Base32 字符索引
int cur_v = 0;
// 当前 Base32 字符代表的数字
int k;
// 当前二进制位索引
for (int i = 0; i < length; i++) {
// 对每个 byte 循环
for (int j = 0; j < 8; j++) {
// 对每个 byte 对应的二进制位循环
k = i * 8 + j;
// 计算当前二进制位索引
if (k == value.length() * 5)
break;
// 二进制位扫描结束,通常 Base32 字符代表的二进制位会大于等于实际长度
// 因此此处主要用于检测不规范 Base32 编码
if (k % 5 == 0) {
cur_v = BASE32STRING.indexOf(value.charAt(cur_i++));
// 转移到下一个 Base32 字符,初始化时转移到第 0 个字符
if (cur_i == value.length() && value.length() % 8 != 0)
cur_v <<= value.length() * 5 % 8;
// 根据 Base32 字符串代表的长度和实际 byte[] 长度
// 修正最末尾 Base32 字符代表的数字。
}
r[i] <<= 1;
r[i] |= (byte) ((cur_v & 16) == 0 ? 0 : 1);
cur_v <<= 1;
// 编码过程的逆过程,同样是移位、送位
}
}
return r;
}
public static void main(String[] args) {
String s = "bs适当モ《方#ぞラ︼Ж┷式来d的ǎΘà的⒐萨芬了?.,<>";
String a = new String(Base32.ToBase32(s.getBytes()));
String b = new String(Base32.ToBytes(a));
System.out.println(a);
System.out.println(b);
}
}