Mar 18 2008

torrents文件的java解释

Category: 技术ssmax @ 21:40:43

翻代码翻出n年前写的东西,当初还想做个tracker的,还去sourceforge申请个项目,没通过。。。怀念一下:

import java.util.*;

public class BitDecoder
{
 //0
 public static final byte ZERO_BYTE = 0x30;
 
 //9
 public static final byte NINE_BYTE = 0x39;
 
 //-
 public static final byte MINUS_BYTE = 0x2D;
 
 //:
 public static final byte COLON_BYTE = 0x3A;
 
 //d
 public static final byte d_BYTE = 0x64;
 
 //e
 public static final byte e_BYTE = 0x65;
 
 //i
 public static final byte i_BYTE = 0x69;
 
 //l
 public static final byte l_BYTE = 0x6c;
 
 //n
 public static final byte NULL_BYTE = 0x6e;
 
 //最大解释层数
 public static int MAX_LAYER = 8;
 
 private int now_layer = 0;
 private String index_key = “”;
 private int key_start = 0;
 private int key_end = 0;
 
 public BitDecoder(String key)
 {
  if(key!=null)
   index_key = key;
 }
 
 public void reset(String key)
 {
  now_layer = 0;
  key_start = 0;
  key_end = 0;
  if(key!=null)
   index_key = key;
  else
   index_key = “”;
 }
 
 public String getkey()
 {
  return index_key;
 }
 
 public int getKeyStart()
 {
  return key_start;
 }
 
 public int getKeyEnd()
 {
  return key_end;
 }
 
 //解出int,用String保存
 private BTDecodeObj decode_int(byte [] bytes,int index) throws Exception
 {
  int till_index = ++index;
  
  byte workingbyte = bytes[till_index];
  
  if(workingbyte == MINUS_BYTE)
  {
   workingbyte = bytes[till_index+1];
   if(workingbyte == ZERO_BYTE)
    throw new Exception(“number -0 is not allowed”);
   else if(workingbyte == e_BYTE)
    throw new Exception(“only minus is not allowed”);
   else if(workingbyte>NINE_BYTE || workingbyte<ZERO_BYTE)
    throw new Exception(“number must be 0-9”);
   else
    till_index++;
  }
  
  while(true)
  {
   workingbyte = bytes[till_index];
   if(workingbyte == e_BYTE)
    break;
   else if(workingbyte>NINE_BYTE || workingbyte<ZERO_BYTE)
    throw new Exception(“number must be 0-9”);
   else
    till_index++;
  }
  
  if(bytes[index]==ZERO_BYTE && till_index!=index+1)
   throw new Exception(“number 0 must be alone”);
  else  
   return new BTDecodeObj(new String(bytes,index,till_index-index),till_index+1);
 }
 
 //解出String
 private BTDecodeObj decode_string(byte [] bytes,int index) throws Exception
 {
  int colon_index = index;
  byte workingbyte = 0x00;
  while(true)
  {
   workingbyte = bytes[colon_index];
   if(workingbyte == COLON_BYTE)
    break;
   else if(workingbyte>NINE_BYTE || workingbyte<ZERO_BYTE)
    throw new Exception(“string length must be 0-9”);
   else
    colon_index++;
  }
  
  if(bytes[index] == ZERO_BYTE && colon_index!=index+1)
   throw new Exception(“string length 0 must follow by :”);
  
  index = Integer.parseInt(new String(bytes,index,colon_index-index));
  colon_index++;

  return new BTDecodeObj(new String(bytes,colon_index,index,”8859_1″),colon_index+index);
 }
 
 //解出List
 private BTDecodeObj decode_list(byte [] bytes,int index) throws Exception
 {
  now_layer++;
  if(now_layer > MAX_LAYER)
   throw new Exception(“too many list or dictionary layer!”);
  
  index++;
  ArrayList resultlist = new ArrayList();
  
  BTDecodeObj tempobj = null;
  
  while(bytes[index] != e_BYTE)
  {
   tempobj = bdecode(bytes,index);
   index = tempobj.getIndex();
   resultlist.add(tempobj.getObj());
  }
  
  now_layer–;
  return new BTDecodeObj(resultlist,index+1);
 }
 
 //解出dict
 private BTDecodeObj decode_dict(byte [] bytes,int index) throws Exception
 {
  now_layer++;
  if(now_layer > MAX_LAYER)
   throw new Exception(“too many list or dictionary layer!”);
  
  index++;
  HashMap resultmap =  new HashMap();
  
  BTDecodeObj tempobj = null;
  String lastkey = “”;
  String nowkey = null;
  
  while(bytes[index] != e_BYTE)
  {
   tempobj = decode_string(bytes,index);
   nowkey = (String)tempobj.getObj();
   if(nowkey.compareTo(lastkey) <= 0)
    throw new Exception(“dictionary lexicographically order error!”);
   
   lastkey = nowkey;
   index = tempobj.getIndex();
   if(key_start==0 && index_key.equals(lastkey))
   {
    key_start = index;
   }
   
   tempobj = bdecode(bytes,index);
   index = tempobj.getIndex();
   if(key_start!=0 && index_key.equals(lastkey))
   {
    key_end = index;
   }
   
   resultmap.put(nowkey,tempobj.getObj());
  }
  
  now_layer–;
  return new BTDecodeObj(resultmap,index+1);
 }
 
 private BTDecodeObj bdecode(byte [] bytes,int index) throws Exception
 {
  if(bytes[index]>=ZERO_BYTE && bytes[index]<=NINE_BYTE)
   return decode_string(bytes,index);
  else if(bytes[index] == d_BYTE)
   return decode_dict(bytes,index);
  else if(bytes[index] == l_BYTE)
   return decode_list(bytes,index);
  else if(bytes[index] == i_BYTE)
   return decode_int(bytes,index);
  else
   throw new Exception(“torrent bencode format error!”);
 }
 
 public Object bdecode(byte [] bytes) throws Exception
 {
  BTDecodeObj resultobj = bdecode(bytes,0);
  if(resultobj.getIndex() != bytes.length)
   throw new Exception(“torrent bencode format error,length exception!”);
  
  return resultobj.getObj();
 }
 
 public int getNowLayer()
 {
  return now_layer;
 }

 public static class BTDecodeObj
{
 Object obj = null;
 int index = 0;
 
 public BTDecodeObj(Object obj,int index)
 {
  this.obj = obj;
  this.index = index;
 }
 
 public Object getObj()
 {
  return obj;
 }
 
 public int getIndex()
 {
  return index;
 }
}
}


Mar 18 2008

Hex转换

Category: 技术ssmax @ 21:28:58

n年前的课题了,今天要用,都忘记了,记录一下

byte to hex 直接java方法:

// convert a single byte b to a 2-char hex string
// with possible leading zero.
String s2 = Integer.toString( ( b & 0xff ) + 0x100, 16 /* radix */ )
		.substring( 1 );

字典法和反向转换,记录自己在无线时候写的一个:

        /*
         *取得byte的16进制字符串
        */     
        private static final String HexString = “0123456789ABCDEF”;
       

        public static String getHexString(byte [] msg_byte)
        {
                StringBuffer sb = new StringBuffer(msg_byte.length * 2);
                for(int i =0;i<msg_byte.length;i++)
                {
                        sb.append(HexString.charAt(0xf&msg_byte[i]>>4)).append(HexString.charAt(msg_byte[i]&0xf));
                }
                return sb.toString();
        }      
               
        public static byte[] getBytesFromHexStr(String s)
        {              
                try    
                {              
                        int i = s.length();
                        byte result[] = new byte[i >> 1];
                        for(int k = 0; k < i;)
                                result[k >> 1] = (byte)(Integer.parseInt(s.substring(k,k+=2),16));
                        return result;
                }
                catch(Exception ex)
                {
                        //ex.printStackTrace();
                        return null;
                }
        }