`

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
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics