decoderbencoding.java

来自「一个基于NetBeans平台开发的」· Java 代码 · 共 190 行

JAVA
190
字号
package com.sinpool.rivercrescent; 

import java.io.*;
import java.util.*;

/**这个类是为了解码Bencoding码的,<br>
 *Bencoding码是python(一种面向对象语言)的编码形式,<br>
 *因为BitTorrent之父Bram Cohen,<br>
 *使用python实现了第一个BT软件,<br>
 *所以BT协议中的数据结构,<br>
 *都遵循python的规则.<br>
 *这也是Bram Cohen所倡导的.<br>
 *<br>
 *<br>
 *<br>
 *创建时间:2005.1.19<br>
 *@author Sinpool.<br>
 *@version 1.0<br>
 *<br>
 **/
public class DecoderBencoding {
	private Hashtable dictionary = new Hashtable();
	private Stack stack = new Stack();
	private int fileByteLength;
	byte[] fileBytes;
	
	/**用来打开需要解码的文件。<br>
	 *<br>
	 *@param f 是一个字符串,<br>
	 *			指出reiverscent元文件的文件名。<br>
	 *<br>
	 */
	public void openFile(String f) throws IOException{
		String filename = "riverfile\\";
		filename += f;
		File file = new File(filename);
		FileInputStream fis = new FileInputStream(file);
		fileBytes = new byte[(int)file.length()];
		fis.read(fileBytes,0,(int)file.length());
                fis.close();        //如果不管就无法改名
		this.fileByteLength = (int)file.length();
	}
	/**用来解析Bencoding码的具体方法.<br>
	 *@param fileBytes 参数fileBytes是被解析的信息<br>
	 *@exception IOException 抛出IOException异常<br>
	 *@see IOException<br>
	 **/
	public void decoderBencoding() throws IOException{
		
		int index = 0,length_index = 0,path_index = 0;
		boolean multiple = false;
		boolean name = true;
		String key = "",keyName = "",keyValue = "",comparePop = "";
		StringBuffer pathValue = new StringBuffer();
		StringBuffer keyLength = new StringBuffer();
		byte charactor = fileBytes[index++];
		charactor = fileBytes[index++];
		stack.push("d");
		while ( !stack.empty() ){
			switch ( charactor ) {
				case 'd' : {stack.push("d");break;}
				case 'l' : {stack.push("l");break;}
				case 'i' : {stack.push("i");break;}
				case 'e' : {
					comparePop = (String)stack.pop();
					if (comparePop.equals("i")){
						if ( keyName.equals("length") && multiple){
							keyName += ++length_index;		//键名是字符串加int
							dictionary.put(keyName,new Integer(Integer.parseInt(keyLength.toString())));
							keyLength.setLength(0);
							name = true;
//System.out.println("keyName: " + keyName);
//System.out.println("keyValue: " + keyLength.toString() );
							break;
						}
						dictionary.put(keyName,new Integer(Integer.parseInt(keyLength.toString())));
			 		}
					if (comparePop.equals("l") && keyName.equals("path")){
						pathValue.deleteCharAt(pathValue.length()-1);
						keyName += ++path_index;			//键名是字符串加int
						dictionary.put(keyName,pathValue.toString());
//System.out.println("keyValue: " + pathValue.toString() );
						pathValue.setLength(0);
					}
					keyLength.setLength(0);
					name = true;
					break;
				}
				default  :
					{
						if ( charactor==':' )
							{
								int temp = Integer.parseInt( keyLength.toString() );
								key = new String(fileBytes,index,temp);
								if (name) 
									{
										keyName = new String(key);
										name = false;
										
										if(keyName.equals("info") || keyName.equals("files")) name = true;
//System.out.println("keyName: " + keyName);
									}
								else
									{
										keyValue = new String(key);
										if ( keyName.equals("type") && keyValue.equals("single") ){
											dictionary.put("type","single");
										}
										if ( keyName.equals("type") && keyValue.equals("multiple") ){
											multiple = true;
											dictionary.put("type","multiple");
										}

										//块信息的处理
										//hash表中第一个块是"0"
                                                                                //pieces 忠于元文件 是块数*20
                                                                                //piece  是保存每个字节的字节数组
										if ( keyName.equals("pieces") ){
											int pieces = temp/20 ;
											Byte[] piece;
											dictionary.put("pieces",new Integer(pieces*20));
											piece = new Byte[pieces*20];
											for (int i=0;i<pieces*20;i++){
												piece[i] = new Byte(fileBytes[index++]);
											}

											dictionary.put("piece",piece);


//System.out.println("dictionary." + i + ": " + dictionary.get(String.valueOf(i)));
											
											keyLength.setLength(0);
											name = true;
											break;
										}
										//对多文件中path的处理
										if ( keyName.equals("path") ){
											pathValue.append(keyValue);
											pathValue.append("/");
											keyLength.setLength(0);
											index += temp;
											break;
										}
										dictionary.put(keyName,keyValue);
//System.out.println("keyValue: " + keyValue );

										name = true;
									}
								index += temp;
								keyLength.setLength(0);
							}
						else keyLength.append( (char) charactor );
					}
			}
			if (index != fileByteLength) charactor = fileBytes[index++];
		}
		dictionary.put("length_index",new Integer(length_index) );
		dictionary.put("path_index",new Integer(path_index) );
	}
	/**<br>
	 *除了BT协议中的键名之外,<br>
	 *还有一些辅助键名,<br>
	 *	比如BitComet中的扩展键名,<br>
	 *	比如BitTorrent plus中的扩展键名,<br>
	 *	还有本软件用于准确获得所需信息所扩展的键名:<br>
	 *		type:	用来表示此BT种子文件任务是单文件还是多文件,<br>
	 *			  	可能获得的值有两个:single和mutiple;<br>
	 *		length_index:<br>
	 *				用来表示此BT种子文件有多少文件。<br>
	 *		length数字:<br>
	 *				数字代表具体某一文件长度;<br>
	 *				例如:length4表示第四个文件长度;<br>
	 *				数字从"1"开始,不是从"0"开始。<br>
	 *		path_index:<br>
	 *				用来表示此BT种子文件有多少path值,<br>
	 *				每个path代表一个文件;<br>
	 *		path数字:<br>
	 *				数字代表具体某一path,<br>
	 *				例如:path4表示第四个文件的path值,<br>
	 *				这个值只出现在多文件时,<br>
	 *				此值包括路径和文件名,<br>
	 *				最上层目录名用键名name的键值所表示;<br>
	 *				数字从"1"开始,不是从"0"开始。<br>
	 *<br>
	 *@return 返回解析后的信息,以Hash表的形式出现<br>
	 **/
	public Hashtable getDictionary(){
		return this.dictionary;
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?