bencode解码实现

字符串:

字符串被如此编码:<字符串长度>:字符串正文.这种表示法没有任何的分界符.
例子:如"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();
}
}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Caesar密码是一种古典密码,它通过将字母按照一定的偏移量进行替换来进行加密和解密。具体来说,对于每个字母,将其按照偏移量k进行移动,如果是加密操作,则向后移动k个位置,如果是解密操作,则向前移动k个位置。这样可以实现简单的字母替换加密。 下面是一个C语言实现的Caesar密码函数的示例代码: ```c void Caesar(char str[], int k, int bEncode) { int i = 0; while (str[i] != '\0') { if (str[i] >= 'A' && str[i] <= 'Z') { if (bEncode) { str[i] = (str[i] - 'A' + k) % 26 + 'A'; // 加密操作 } else { str[i] = (str[i] - 'A' - k + 26) % 26 + 'A'; // 解密操作 } } else if (str[i] >= 'a' && str[i] <= 'z') { if (bEncode) { str[i] = (str[i] - 'a' + k) % 26 + 'a'; // 加密操作 } else { str[i] = (str[i] - 'a' - k + 26) % 26 + 'a'; // 解密操作 } } i++; } } ``` 这个函数接受三个参数:待加密/解密的字符串、偏移量k和一个标志位bEncode,用于指示是加密还是解密操作。函数会对字符串中的每个字母进行加密或解密,并将结果直接修改在原字符串中。 示例调用代码如下: ```c char str[] = "Hello, World!"; int k = 3; int bEncode = 1; // 加密操作 Caesar(str, k, bEncode); printf("加密后的字符串:%s\n", str); // 输出:Khoor, Zruog! ``` 请注意,这只是Caesar密码的一个简单实现,实际应用中可能需要考虑更多的情况,比如非字母字符的处理、偏移量的范围等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值