字符串:
字符串被如此编码:<字符串长度>:字符串正文.这种表示法没有任何的分界符.
例子:如"8:announce"指"announce".
整数:
整数被如此编码:<i>整数值<e>.可以为负数,如'i-3e'
例子:'i3e' 指 3.
列表:
列表是如此被表示的:<l>Bencode Value<e>,
列表可以用来表示多个对象.
列表内容可以包括字符串,整数,字典,甚至列表本身.
例子:'l4:spam4:eggse' 指 [ "spam", eggs" ]
字典:
字典是一个一对一的映射.它表示了一个主键(必须为字符串)和一个数据项(可以为任何Bencode值)的关系.字典可以用来表示一个对象的多种属性.
字典是如此被编码:<d><bencoded string><bencoded element><e>
注意:字典必须根据主键预排序.
package com.norkts.torrents;
import java.io.*;
import java.nio.ByteBuffer;
import java.util.*;
/**
* bencode解码实现
* @author norkts<norkts@gmail.com>
* @date 2017-06-21
* @version 1.0
*/
public class BencodeDecoder {
public static Object decode(byte[] data){
ByteBuffer buffer = ByteBuffer.wrap(data);
return decode(buffer);
}
public static Object decode(ByteBuffer buffer){
Stack<Object> endStack = new Stack<Object>();
while (buffer.hasRemaining()){
byte ch = buffer.get();
if(ch >= '0' & ch <= '9'){
buffer.position(buffer.position() - 1);
//string
byte[] lenByte = readUntil(buffer, ':');
int len = Integer.parseInt(new String(lenByte));
lenByte = new byte[len];
buffer.get(lenByte);
String str = new String(lenByte);
if(endStack.empty()){
endStack.push(new LinkedList<Object>());
}
setStackVal(endStack, str);
//继续执行下一次
continue;
}
if(ch == 'i'){
//字符串处理
byte[] temp = readUntil(buffer, 'e');
Long val = Long.parseLong(new String(temp));
if(endStack.empty()){
endStack.push(new LinkedList<Object>());
}
setStackVal(endStack, val);
continue;
}
if(ch == 'l'){
//列表处理
endStack.push(new LinkedList<Object>());
continue;
}
if(ch == 'd'){
//字典类型开始解码
endStack.push(new LinkedHashMap<Object, Object>());
continue;
}
if(ch == 'e'){
Object last = endStack.pop();
if(endStack.empty()){
return last;
}
setStackVal(endStack, last);
}
}
return endStack.empty() ? null : endStack.pop();
}
private static byte[] readUntil(ByteBuffer buff, char end){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (true){
byte ch = buff.get();
if(ch == end){
break;
}
baos.write(ch);
}
return baos.toByteArray();
}
private static void setStackVal(Stack<Object> stack, Object val){
Object prev = stack.peek();
if(prev instanceof List){
((List)prev).add(val);
}else if(prev instanceof Map){
Pair<Object, Object> entry = new Pair<Object, Object>(val, null);
stack.push(entry);
}else if(prev instanceof Pair){
Pair<Object, Object> entry = (Pair<Object, Object>)stack.pop();
entry.setVal(val);
prev = stack.peek();
((Map<Object, Object>)prev).put(entry.getKey(), entry.getVal());
}
}
static class Pair<K,V>{
private K key;
private V val;
public Pair(K k, V v){
this.key = k;
this.val = v;
}
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public V getVal() {
return val;
}
public void setVal(V val) {
this.val = val;
}
}
public static void main(String[] argv){
/* Object obj = BencodeDecoder.decode("l:3:abci45678el:3:xxxi123ed3:key3:val4:name5:zhangeee".getBytes());
System.out.println(obj);
obj = BencodeDecoder.decode("d3:key3:val4:name5:zhang3:mapd3:key3:vali123e4:xxxxee".getBytes());
System.out.println(obj);*/
try {
File f = new File("Q:\\study\\torrents\\0000405710f78d75c5d1dd9cc69ffdd7d1561bb1.torrent");
FileInputStream inputStream = new FileInputStream(f);
ByteBuffer buff = ByteBuffer.allocate((int)f.length());
inputStream.getChannel().read(buff);
inputStream.close();
buff.flip();
Object o = BencodeDecoder.decode(buff);
System.out.println(o);
System.out.println((((Map<String, Object>)((Map<String, Object>)o).get("info"))).keySet());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
分享到:
相关推荐
最初的Bittorrent系统是用python实现的,其中的Bencode编解码采用了递归的方式,后续的很多BT客户端实现都直接拷贝了这种方式。这就为针对Bencode编码实现的攻击提供了可能。首先构造了有一定递归深度的torrent文件...
锈本码 Rust 语言中的 Bencode 解码器实现 目前它正在开发中。 更多信息即将推出
本码 Go中的Bencode实现安装$ go get github.com/marksamman/bencode用法编码bencode.Encode使用map [string] interface {}作为参数,并返回一个字节数组。 例子: package mainimport ("fmt""github....
最初的Bittorrent系统是用python实现的,其中的Bencode编解码采用了递归的方式,后续的很多BT客户端实现都直接拷贝了这种方式。这就为针对Bencode编码实现的攻击提供了可能。首先构造了有一定递归深度的torrent文件...
Bencode 解码器/编码器使用 Elixir 数据结构。 安装 将其添加到您的mix.exs依赖项中: defp deps do [{ :elixir_bencode , " ~> 1.0.0 " }] end 例子 ## Encode strings (with thrown exceptions) Bencode . ...
这是Bencode for Java的实现。 Bencode用于DHT,Torrent和Google DataServer。 它是一种轻量级的快速数据序列化。 基准测试 这里是与其他主要数据序列化方法相比该库的一些示例。 序列化/编码 方法 时间在米尔斯 ...
关于BERadio是用于在受限无线电链路环境中进行有效通信的编码规范和实现。 它被构想并用于内的无线通信。 它与 (一个用于构建灵活的遥测解决方案的多通道,多协议数据采集和图形化工具包)一起,为网关侧的提供了...
对于许多本机数据类型,此程序包实现了与Bencode格式之间的快速无缝编码/解码。 为了获得我们使用和手动优化的解析器,因此该库被视为BEncode和AttoBencode包的替代品。 格式 Bencode与JSON非常相似:它具有字典...
蚁群 介绍 AntColony(Github)是findit磁力搜索引擎的核心。在DHT网络中,收集活跃资源的infohash,下载并解析资源的种子文件,存入数据库等。AntColony是某些功能的合集,也可以单独运行其中的部分功能,所以...
有一个实现列表。 另请参见文件。 Bencodex 是一种序列化格式,它扩展了 BitTorrent 的 。 由于它是 Bencoding 的超集,每个有效的 Bencoding 表示都是相同含义的有效 Bencodex 表示(即,表示相同的值)。 ...