自己写的BASE32程序

来源:互联网 发布:网络沙发什么意思 编辑:程序博客网 时间:2024/05/21 17:21

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);

 }

}