Java实现BT种子解析

来源:互联网 发布:微信小说系统源码 编辑:程序博客网 时间:2024/04/28 13:44

BT种子结构

  • announce:tracker服务器的URL(字符串)
  • announce-list(可选):备用tracker服务器列表(列表)
  • creation date(可选):种子创建的时间,Unix标准时间格式,从1970 1月1日 00:00:00到创建时间的秒数(整数)
  • comment(可选):备注(字符串)
  • created by(可选):创建人或创建程序的信息(字符串)
  • info:一个字典结构,包含文件的主要信息,为分二种情况:单文件结构或多文件结构(目录)
    1. 单文件结构如下:
      • length:文件长度,单位字节(整数)
      • md5sum(可选):长32个字符的文件的MD5校验和,BT不使用这个值,只是为了兼容一些程序所保留!(字符串)
      • name:文件名(字符串)
      • piece length:每个块的大小,单位字节(整数)
      • pieces:每个块的20个字节的SHA1 Hash的值(二进制格式)
    2. 多文件结构如下:
      • files:一个字典结构
      • length:文件长度,单位字节(整数)
      • md5sum(可选):同单文件结构中相同
      • path:文件的路径和名字,是一个列表结构,如”test”test.txt(列表) 列表为l4:test8test.txte
      • name:最上层的目录名字(字符串)
      • piece length:同单文件结构中相同(整数)
      • pieces:同单文件结构中相同 (二进制格式)

代码实现

解析工具类声明

package org.hanmeis.bt;import org.hanmeis.bt.bean.BitTorrentInfo;import org.hanmeis.bt.bean.Files;import org.hanmeis.bt.bean.Info;import java.io.*;import java.util.LinkedList;import java.util.List;/** * 代码中并未采用网上现有的递归算法进行解析,而是使用键值匹配的方式。 * 然而当前代码实现中还存在着一些bug,如键和值相同的情况。 * 对此bug修正方法,当前的想法是创建set记录已经出现过的键值情况。 * Created by zhao.wu on 2016/12/8. */public class BitTorrents {    public static BitTorrentInfo parse(File btFile) throws Exception {        return new BitTorrents().analyze(new FileInputStream(btFile));    }    public static BitTorrentInfo parse(String btFilePath) throws Exception {        return new BitTorrents().analyze(new FileInputStream(btFilePath));    }    private BitTorrentInfo analyze(InputStream is) throws Exception {        BitTorrentInfo btInfo = new BitTorrentInfo();        String key = null;        StringBuilder strLengthBuilder = new StringBuilder();        int tempByte;        while ((tempByte = is.read()) != -1) {            char temp = (char) tempByte;            switch (temp) {                case 'i':                    StringBuilder itempBuilder = new StringBuilder();                    char iTemp;                    while ((iTemp = (char) is.read()) != 'e') {                        itempBuilder.append(iTemp);                    }                    btInfo.setValue(key, itempBuilder.toString());                    break;                case '0': case '1': case  '2': case '3': case '4': case  '5': case '6': case '7': case '8': case '9':                    strLengthBuilder.append(temp);                    break;                case ':':                    int strLen = Integer.parseInt(strLengthBuilder.toString());                    strLengthBuilder = new StringBuilder();                    byte[] tempBytes = new byte[strLen];                    is.read(tempBytes);                    if (key != null && key.equals("pieces")) {                        btInfo.setValue(key, tempBytes);                    } else {                        String tempStr = new String(tempBytes);                        if (BitTorrentInfo.keyList.contains(tempStr)) {                            key = tempStr;                            if (tempStr.equals("announce-list")) {                                btInfo.setAnnounceList(new LinkedList<String>());                            } else if (tempStr.equals("info")) {                                btInfo.setInfo(new Info());                            } else if (tempStr.equals("files")) {                                btInfo.getInfo().setFiles(new LinkedList<Files>());                                btInfo.getInfo().getFiles().add(new Files());                            } else if (tempStr.equals("length")) {                                List<Files> tempFiles = btInfo.getInfo().getFiles();                                if (tempFiles != null) {                                    if (tempFiles.isEmpty() || tempFiles.get(tempFiles.size() - 1).getLength() != 0) {                                        tempFiles.add(new Files());                                    }                                }                            } else if (tempStr.equals("md5sum")) {                                List<Files> tempFiles = btInfo.getInfo().getFiles();                                if (tempFiles != null) {                                    if (tempFiles.isEmpty() || tempFiles.get(tempFiles.size() - 1).getMd5sum() != null) {                                        tempFiles.add(new Files());                                    }                                }                            } else if (tempStr.equals("path")) {                                List<Files> tempFilesList = btInfo.getInfo().getFiles();                                if (tempFilesList.isEmpty()) {                                    Files files = new Files();                                    files.setPath(new LinkedList<String>());                                    tempFilesList.add(files);                                } else {                                    Files files = tempFilesList.get(tempFilesList.size() - 1);                                    if (files.getPath() == null) {                                        files.setPath(new LinkedList<String>());                                    }                                }                            }                        } else {                            btInfo.setValue(key, tempStr);                        }                    }                    break;            }        }        return btInfo;    }    public static void main(String[] args) throws Exception {        System.out.println(parse("E://【BT吧】[1080p]-鲁滨逊漂流记-Robinson Crusoe-1.73GB.torrent"));    }}

beam申明

最外层BitTorrentInfo

package org.hanmeis.bt.bean;import java.util.Arrays;import java.util.List;/** * Created by zhao.wu on 2016/12/8. */public class BitTorrentInfo {    public static List<String> keyList;    static{        String[] keys = {"announce", "announce-list", "creation date", "comment", "created by",                "info", "length", "md5sum", "name", "piece length","pieces", "files", "path"};        keyList = Arrays.asList(keys);    }    private String announce;    private List<String> announceList;    private long creationDate;    private String comment;    private String createBy;    private Info info;    public BitTorrentInfo() {    }    //getter and setter  and tostring    public void setValue(String key, Object value) throws Exception {        if(!keyList.contains(key)){            throw new Exception("not contains this key: " + key);        }else{            switch (key){                case "announce":this.setAnnounce(value.toString());break;                case "announce-list":this.getAnnounceList().add(value.toString());break;                case "creation date":this.setCreationDate(Long.parseLong(value.toString()));break;                case "comment":this.setComment(value.toString());break;                case "created by":this.setCreateBy(value.toString());break;                case "length":                    List<Files> filesList1 = this.getInfo().getFiles();                    if(filesList1 != null){                        Files files = this.getInfo().getFiles().get(filesList1.size()-1);                        files.setLength(Long.parseLong(value.toString()));                    }else {                        this.getInfo().setLength(Long.parseLong(value.toString()));                    }                    break;                case "md5sum":                    List<Files> filesList2 = this.getInfo().getFiles();                    if(filesList2 != null){                        Files files = this.getInfo().getFiles().get(filesList2.size()-1);                        files.setMd5sum(value.toString());                    }else {                        this.getInfo().setMd5sum(value.toString());                    }                    break;                case "name":                    this.getInfo().setName(value.toString());                    break;                case "piece length":                    this.getInfo().setPiecesLength(Long.parseLong(value.toString()));                    break;                case "pieces":                    this.getInfo().setPieces((byte[])value);                    break;                case "path":                    List<Files> filesList3 = this.getInfo().getFiles();                    Files files3 = filesList3.get(filesList3.size()-1);                    files3.getPath().add(value.toString());                    break;            }        }    }    }

第一层Info

package org.hanmeis.bt.bean;import java.util.Arrays;import java.util.List;/** * Created by zhao.wu on 2016/12/8. */public class Info{    private String name;    private byte[] pieces;    private long piecesLength;    private long length;    private String md5sum;    private List<Files> files;    public Info() {    }    //getter and setter  and tostring}

第二层Files

package org.hanmeis.bt.bean;import java.util.List;/** * Created by zhao.wu on 2016/12/8. */public class Files{    private long length;    private String md5sum;    private List<String> path;    public Files() {    }    //getter and setter  and tostring}
0 0
原创粉丝点击