在好例子网,分享、交流、成长!
您当前所在位置:首页Python 开发实例Python语言基础 → bt种子文件解析 含源码下载

bt种子文件解析 含源码下载

Python语言基础

下载此实例
  • 开发语言:Python
  • 实例大小:0.15M
  • 下载次数:20
  • 浏览次数:2535
  • 发布时间:2013-10-21
  • 实例类别:Python语言基础
  • 发 布 人:crazycode
  • 文件格式:.zip
  • 所需积分:2
 相关标签: 种子

实例介绍

【实例简介】
【实例截图】

【核心代码】

{BTTorrent B编码(Bencoding)格式分析}
unit DxBencoding;

interface
uses Classes,SysUtils,Generics.Collections;

type

  (*
  Torrent文件格式
  Multi-file Torrent 多文件
├─announce
├─announce-list
├─comment
├─comment.utf-8
├─creation date
├─encoding
├─info
│ ├─files
│ │ ├─length
│ │ ├─path
│ │ └─path.utf-8
│ ├─name
│ ├─name.utf-8
│ ├─piece length
│ ├─pieces
│ ├─publisher
│ ├─publisher-url
│ ├─publisher-url.utf-8
│ └─publisher.utf-8
└─nodes


Single-File Torrent 单文件
├─announce
├─announce-list
├─comment
├─comment.utf-8
├─creation date
├─encoding
├─info
│ ├─length
│ ├─name
│ ├─name.utf-8
│ ├─piece length
│ ├─pieces
│ ├─publisher
│ ├─publisher-url
│ ├─publisher-url.utf-8
│ └─publisher.utf-8
└─nodes
  *)
  //B编码支持的数据类型
  TDxBenValueTypes = (DBV_String,DBV_Int,DBV_List,DBV_Dictionary);
  //B编码的节点,类似于JSON节点,
  TDxBenValue = class
  private
    FParent: TDxBenValue;
  protected
    function GetType:TDxBenValueTypes; virtual; abstract;
    procedure Parser(str: string);virtual;abstract;
    function GetAsInteger: Integer;virtual;abstract;
    function GetAsString: string;virtual;abstract;
    function GetObject: TDxBenValue;virtual;
  public
    constructor Create;overload;virtual;
    constructor Create(str: string);overload;virtual;
    property ValueType: TDxBenValueTypes read GetType;
    function ToString: string;override;
    property Parent: TDxBenValue read FParent;
    property AsInteger: Integer read GetAsInteger;
    property AsString: string read GetAsString;
    property AsValueObject: TDxBenValue read GetObject;
  end;

  TDxBenInt = class(TDxBenValue)
  private
    FValue: Integer;
  protected
    function GetType:TDxBenValueTypes;override;
    function GetAsInteger: Integer;override;
    procedure Parser(str: string);override;
    function GetAsString: string;override;
    function GetObject: TDxBenValue;override;
  public
    constructor Create;override;
    function ToString: string;override;
  end;

  TDxBenString = class(TDxBenValue)
  private
    FValue: string;
  protected
    function GetType:TDxBenValueTypes;override;
    function GetAsString: string;override;
    function GetObject: TDxBenValue;override;
    function GetAsInteger: Integer;override;
    procedure Parser(str: string);override;
  public
    function ToString: string;override;
  end;

  TDxBenDictionary = class;
  TDxBenList = class(TDxBenValue)
  private
    FList: TList;
    function GetCount: Integer;
    function GetValues(index: Integer): TDxBenValue;
  protected
    procedure Parser(str: string);override;
    procedure ParserToList(var P: Pchar;List: TDxBenList);
    procedure ParserToDictionary(var p: PChar;Dict: TDxBenDictionary);
    function GetType:TDxBenValueTypes;override;
    function GetAsString: string;override;
    function GetObject: TDxBenValue;override;
    function GetAsInteger: Integer;override;
  public
    procedure Clear;
    constructor Create; override;
    constructor CreateFromString(str: string);
    destructor Destroy;override;
    function ToString: string;override;
    property Count: Integer read GetCount;
    property Values[index: Integer]: TDxBenValue read GetValues;
  end;

  TDxBenDictionary = class(TDxBenValue)
  private
    FDict: TDictionary<string,TDxBenValue>;
    function GetCount: Integer;
    function GetValues(Key: string): TDxBenValue;
  protected
    procedure ParserToList(var P: Pchar;List: TDxBenList);
    procedure ParserToDictionary(var p: PChar;Dict: TDxBenDictionary);

    procedure Parser(str: string);override;
    function GetType:TDxBenValueTypes;override;
    function GetAsString: string;override;
    function GetObject: TDxBenValue;override;
    function GetAsInteger: Integer;override;
  public
    procedure Clear;
    constructor Create;override;
    destructor Destroy;override;
    function ToString: string;override;
    property Count: Integer read GetCount;
    property Values[Key: string]: TDxBenValue read GetValues;
  end;

  TDxBtInfo = class(TDxBenDictionary)
  private
    function GetSingleFile: Boolean;
    function GetFiles: TDxBenList;
    function GetName: string;
    function GetNameUtf8: string;
    function Getpublisher: string;
    function GetpublisherUtf8: string;
    function Getpublisherurl: string;
    function GetpublisherurlUtf8: string;
  public
    property SingleFile: Boolean read GetSingleFile;
    property Files: TDxBenList read GetFiles;
    property Name: string read GetName;
    property NameUtf8: string read GetNameUtf8;
    property publisher: string read Getpublisher;
    property publisherUtf8: string read GetpublisherUtf8;
    property publisherurl: string read Getpublisherurl;
    property publisherurlUtf8: string read GetpublisherurlUtf8;
  end;

  TDxTorrentFile = class
  private
    FDict: TDxBenDictionary;
    procedure ParserStream(Stream: TStream;Dict: TDxBenDictionary);overload;
    procedure ParserStreamToList(Stream: TStream; List: TDxBenList);
    function GetComment: string;
    function GetEncoding: string;
    function GetCreator: string;
    function Getannounce: string;
    function Getannounce_list: TDxBenList;
    function GetBtInfo: TDxBtInfo;
    function GetCreateDate: TDateTime;
  public
    procedure Clear;
    constructor Create;
    destructor Destroy;override;
    procedure LoadFromFile(FileName: string);
    procedure LoadFromStream(Stream: TStream);
    property Comment: string read GetComment;
    property Encoding: string read GetEncoding;
    property Creator: string read GetCreator;
    property announce: string read Getannounce;
    property announce_list: TDxBenList read Getannounce_list;
    property BtInfo: TDxBtInfo read GetBtInfo;
    property CreateDate: TDateTime read GetCreateDate;
  end;
implementation

{ TDxBenValue }

constructor TDxBenValue.Create;
begin
  FParent := nil;
end;

constructor TDxBenValue.Create(str: string);
begin
  Create;
  Parser(str);
end;


function TDxBenValue.GetObject: TDxBenValue;
begin
  Result := Self;
end;

function TDxBenValue.ToString: string;
begin
  Result := '';
end;

{ TDxBenInt }


constructor TDxBenInt.Create;
begin
  inherited;
  FValue := 0;
end;

function TDxBenInt.GetAsInteger: Integer;
begin
  Result := FValue;
end;

function TDxBenInt.GetAsString: string;
begin
  Result := IntToStr(FValue);
end;

function TDxBenInt.GetObject: TDxBenValue;
begin
  Result := Self;
end;

function TDxBenInt.GetType: TDxBenValueTypes;
begin
  Result := DBV_Int;
end;

procedure TDxBenInt.Parser(str: string);
var
  len: Integer;
begin
  len := Length(str);
  if (UpperCase(str[1]) = 'I') and (UpperCase(str[len]) = 'E') then
  begin
    Str := Copy(str,2,len - 2);
    if not TryStrToInt(str,FValue) then
      raise Exception.Create('无效的B编码整数格式');
  end
  else raise Exception.Create('无效的B编码整数格式');
end;

function TDxBenInt.ToString: string;
begin
  Result := 'i' inttostr(FValue) 'e';
end;

{ TDxBenString }

function TDxBenString.GetAsInteger: Integer;
begin
  raise Exception.Create('字符串类型数据');
end;

function TDxBenString.GetAsString: string;
begin
  Result := FValue;
end;

function TDxBenString.GetObject: TDxBenValue;
begin
  Result := Self;
end;

function TDxBenString.GetType: TDxBenValueTypes;
begin
  Result := DBV_String;
end;

procedure TDxBenString.Parser(str: string);
var
  ipos: Integer;
  str1: string;
begin
  FValue := '';
  ipos := Pos(':',str);
  if ipos <= 1 then
    raise Exception.Create('无效的数据格式')
  else
  begin
    str1 := Copy(str,1,ipos - 1);
    if not TryStrToInt(str1,ipos) then
      raise Exception.Create('无效的数据格式');
    FValue := Copy(str,ipos 1,ipos);
  end;
end;

function TDxBenString.ToString: string;
var
  len: Integer;
begin
  len := Length(FValue);
  if len > 0 then
    Result := IntToStr(len)   ':' FValue
  else Result := '';
end;

{ TDxBenList }

procedure TDxBenList.Clear;
begin
  while FList.Count > 0 do
  begin
    TDxBenValue(FList[FList.Count - 1]).Free;
    FList.Delete(FList.Count - 1);
  end;
end;

constructor TDxBenList.Create;
begin
  inherited;
  FList := TList.Create;
end;

constructor TDxBenList.CreateFromString(str: string);
begin
  Create;
  Parser(str);
end;

destructor TDxBenList.Destroy;
begin
  Clear;
  FList.Free;
  inherited;
end;

function TDxBenList.GetAsInteger: Integer;
begin
  raise Exception.Create('列表不支持');
end;

function TDxBenList.GetAsString: string;
begin
  raise Exception.Create('列表不支持');
end;

function TDxBenList.GetCount: Integer;
begin
  Result := FList.Count;
end;

function TDxBenList.GetObject: TDxBenValue;
begin
  Result := inherited;
end;

function TDxBenList.GetType: TDxBenValueTypes;
begin
  Result := DBV_List;
end;

function TDxBenList.GetValues(index: Integer): TDxBenValue;
begin
  if index in [0..FList.Count-1] then
    Result := FList[index]
  else Result := nil;
end;

procedure TDxBenList.Parser(str: string);
var
  len: Integer;
  p: PChar;
begin
  len := Length(str);
  Clear;
  if (UpperCase(str[1]) = 'L') and (UpperCase(str[len]) = 'E') then
  begin
    Str := Copy(str,2,len - 2);
    p := @str[1];
    ParserToList(p,nil);
  end
  else raise Exception.Create('无效的B编码列表格式');
end;

procedure TDxBenList.ParserToDictionary(var p: PChar; Dict: TDxBenDictionary);
type
  TParserState = (PS_None,PS_Key,PS_Value);
var
  t: Char;
  st: string;
  FInt: Integer;
  IntValue: TDxBenInt;
  ListValue: TDxBenList;
  StrValue: TDxBenString;
  DicValue: TDxBenDictionary;
  Parstate: TParserState;
  key: string;
begin
  //开始解析
  Parstate := PS_None;
  while p^ <> ''  do
  begin
    t := P^;
    case t of
    'i':
      begin
        //整数
        if Parstate <> PS_Value then
          raise Exception.Create('B编码字典的Key必须是字符串!');
        Inc(p);
        st := '';
        while p^ <> 'e' do
        begin
          if not CharInSet(p^, ['-','0'..'9']) then
            raise Exception.Create('无效的数据类型');
          st := st   p^;
          Inc(p);
        end;
        if not TryStrToInt(st,FInt) then
          raise Exception.Create('无效的数据类型i' st 'e');
        IntValue := TDxBenInt.Create;
        IntValue.FValue := FInt;
        IntValue.FParent := Dict;
        Dict.FDict[Key] := IntValue;
        Inc(p);
      end;
    'l':
      begin
        if Parstate <> PS_Value then
          raise Exception.Create('B编码字典的Key必须是字符串!');
        Inc(p);
        ListValue := TDxBenList.Create;
        ListValue.FParent := Dict;
        Dict.FDict[Key] := ListValue;
        ParserToList(p,ListValue);
      end;
    'd':
      begin
        if Parstate <> PS_Value then
          raise Exception.Create('B编码字典的Key必须是字符串!');
        Inc(p);
        DicValue := TDxBenDictionary.Create;
        DicValue.FParent := Dict;
        Dict.FDict[Key] := DicValue;
        ParserToDictionary(p,DicValue);
      end;
    'e':
      begin
        if Parstate = PS_Value then
          Parstate := PS_None
        else if Parstate = PS_None then
          Break;
      end;
    else
      begin
        st := '';
        while p^ <> ':' do
        begin
          if not CharInSet(p^, ['-','0'..'9']) then
            raise Exception.Create('无效的数据类型');
          st := st   p^;
          Inc(p);
        end;
        if not TryStrToInt(st,FInt) then
          raise Exception.Create('无效的数据类型' st);
        //读取字符串
        Inc(p);
        if StrLen(p) < FInt then
          raise Exception.Create('字符串解析长度不够');
        SetLength(st,Fint);
        Move(p^,Pointer(St)^,FInt*Sizeof(Char));
        Inc(p,Fint);
        if Parstate = PS_None then
        begin
          key := st;
          if Dict.FDict.ContainsKey(st) then
            raise Exception.Create('字典存在重复信息');
          Dict.FDict.Add(st,nil);
          Parstate := PS_Value;
        end
        else if Parstate = PS_Value then
        begin
          StrValue := TDxBenString.Create;
          StrValue.FParent := Dict;
          StrValue.FValue := st;
          Dict.FDict[Key] := StrValue;
        end;
      end;
    end;
  end;
end;

procedure TDxBenList.ParserToList(var P: PChar; List: TDxBenList);
var
  t: Char;
  st: string;
  FInt: Integer;
  IntValue: TDxBenInt;
  ListValue: TDxBenList;
  StrValue: TDxBenString;
  DicValue: TDxBenDictionary;
begin
  //开始解析
  while p^ <> ''  do
  begin
    t := P^;
    case t of
    'i':
      begin
        //是一个整数
        Inc(p);
        st := '';
        while p^ <> 'e' do
        begin
          if not CharInSet(p^, ['-','0'..'9']) then
            raise Exception.Create('无效的数据类型');
          st := st   p^;
          Inc(p);
        end;
        if not TryStrToInt(st,FInt) then
          raise Exception.Create('无效的数据类型i' st 'e');
        IntValue := TDxBenInt.Create;
        IntValue.FValue := FInt;
        if List = nil then
        begin
          IntValue.FParent := Self;
          FList.Add(IntValue);
        end
        else
        begin
          IntValue.FParent := List;
          List.FList.Add(IntValue)
        end;
        Inc(p);
      end;
    'l':
      begin
        //列表
        Inc(p);
        ListValue := TDxBenList.Create;
        if List = nil then
        begin
          ListValue.FParent := Self;
          FList.Add(ListValue);
        end
        else
        begin
          ListValue.FParent := List;
          List.FList.Add(ListValue)
        end;
        ParserToList(p,ListValue);
      end;
    'd':
      begin
        //字典
        Inc(p);
        DicValue := TDxBenDictionary.Create;
        if List = nil then
        begin
          DicValue.FParent := Self;
          FList.Add(DicValue);
        end
        else
        begin
          DicValue.FParent := List;
          List.FList.Add(DicValue)
        end;
        ParserToDictionary(p,DicValue);
      end;
    'e': Break;//结束了
    else
      begin
        //字符串
        st := '';
        while p^ <> ':' do
        begin
          if not CharInSet(p^, ['-','0'..'9']) then
            raise Exception.Create('无效的数据类型');
          st := st   p^;
          Inc(p);
        end;
        if not TryStrToInt(st,FInt) then
          raise Exception.Create('无效的数据类型' st);
        //读取字符串
        Inc(p);
        if StrLen(p) < FInt then
          raise Exception.Create('字符串解析长度不够');
        StrValue := TDxBenString.Create;
        SetLength(StrValue.FValue,Fint);
        Move(p^,Pointer(StrValue.FValue)^,FInt*Sizeof(Char));
        if List = nil then
        begin
          StrValue.FParent := Self;
          FList.Add(StrValue);
        end
        else
        begin
          StrValue.FParent := List;
          List.FList.Add(StrValue)
        end;
        Inc(p,Fint);
      end;
    end;
  end;
end;

function TDxBenList.ToString: string;
var
  i: Integer;
  V: TDxBenValue;
begin
  for i := 0 to FList.Count - 1 do
  begin
    V := FList[i];
    Result := Result   V.ToString;
  end;
end;

{ TDxBenDictionary }

procedure TDxBenDictionary.Clear;
var
  Pair: TPair<string,TDxBenValue>;
begin
  for Pair in FDict do
  begin
    Pair.Value.Free;
  end;
  FDict.Clear;
end;

constructor TDxBenDictionary.Create;
begin
  FDict := TDictionary<string,TDxBenValue>.Create;
end;

destructor TDxBenDictionary.Destroy;
begin
  Clear;
  FDict.Free;
  inherited;
end;

function TDxBenDictionary.GetAsInteger: Integer;
begin
  raise Exception.Create('字典不支持');
end;

function TDxBenDictionary.GetAsString: string;
begin
  raise Exception.Create('字典不支持');
end;

function TDxBenDictionary.GetCount: Integer;
begin
  Result := FDict.Count;
end;

function TDxBenDictionary.GetObject: TDxBenValue;
begin
  Result := Self;
end;

function TDxBenDictionary.GetType: TDxBenValueTypes;
begin
  Result := DBV_Dictionary;
end;

function TDxBenDictionary.GetValues(Key: string): TDxBenValue;
begin
   if FDict.ContainsKey(Key) then
     Result := FDict[Key]
   else Result := nil;
end;

procedure TDxBenDictionary.Parser(str: string);
var
  len: Integer;
  p: PChar;
begin
  len := Length(str);
  Clear;
  if (UpperCase(str[1]) = 'D') and (UpperCase(str[len]) = 'E') then
  begin
    Str := Copy(str,2,len - 2);
    p := @str[1];
    ParserToDictionary(p,Self);
  end
  else raise Exception.Create('无效的B编码字典格式');
end;

procedure TDxBenDictionary.ParserToDictionary(var p: PChar;
  Dict: TDxBenDictionary);
type
  TParserState = (PS_None,PS_Key,PS_Value);
var
  t: Char;
  st: string;
  FInt: Integer;
  IntValue: TDxBenInt;
  ListValue: TDxBenList;
  StrValue: TDxBenString;
  DicValue: TDxBenDictionary;
  Parstate: TParserState;
  key: string;
begin
  //开始解析
  Parstate := PS_None;
  while p^ <> ''  do
  begin
    t := P^;
    case t of
    'i':
      begin
        //整数
        if Parstate <> PS_Value then
          raise Exception.Create('B编码字典的Key必须是字符串!');
        Inc(p);
        st := '';
        while p^ <> 'e' do
        begin
          if not CharInSet(p^, ['-','0'..'9']) then
            raise Exception.Create('无效的数据类型');
          st := st   p^;
          Inc(p);
        end;
        if not TryStrToInt(st,FInt) then
          raise Exception.Create('无效的数据类型i' st 'e');
        IntValue := TDxBenInt.Create;
        IntValue.FValue := FInt;
        IntValue.FParent := Dict;
        Dict.FDict[Key] := IntValue;
        Inc(p);
        Parstate := PS_None;
      end;
    'l':
      begin
        if Parstate <> PS_Value then
          raise Exception.Create('B编码字典的Key必须是字符串!');
        Inc(p);
        ListValue := TDxBenList.Create;
        ListValue.FParent := Dict;
        Dict.FDict[Key] := ListValue;
        ParserToList(p,ListValue);
        Parstate := PS_None;
      end;
    'd':
      begin
        if Parstate <> PS_Value then
          raise Exception.Create('B编码字典的Key必须是字符串!');
        Inc(p);
        DicValue := TDxBenDictionary.Create;
        DicValue.FParent := Dict;
        Dict.FDict[Key] := DicValue;
        ParserToDictionary(p,DicValue);
        Parstate := PS_None;
      end;
    'e':
      begin
        if Parstate = PS_Value then
          Parstate := PS_None
        else if Parstate = PS_None then
          Break;
      end;
    else
      begin
        st := '';
        while p^ <> ':' do
        begin
          if not CharInSet(p^, ['-','0'..'9']) then
            raise Exception.Create('无效的数据类型');
          st := st   p^;
          Inc(p);
        end;
        if not TryStrToInt(st,FInt) then
          raise Exception.Create('无效的数据类型' st);
        //读取字符串
        Inc(p);
        if StrLen(p) < FInt then
          raise Exception.Create('字符串解析长度不够');
        SetLength(st,Fint);
        Move(p^,Pointer(St)^,FInt*Sizeof(Char));
        Inc(p,Fint);
        if Parstate = PS_None then
        begin
          key := st;
          if Dict.FDict.ContainsKey(st) then
            raise Exception.Create('字典存在重复信息');
          Dict.FDict.Add(st,nil);
          Parstate := PS_Value;
        end
        else if Parstate = PS_Value then
        begin
          StrValue := TDxBenString.Create;
          StrValue.FParent := Dict;
          StrValue.FValue := st;
          Dict.FDict[Key] := StrValue;
          Parstate := PS_None;
        end;
      end;
    end;
  end;
end;

procedure TDxBenDictionary.ParserToList(var P: Pchar; List: TDxBenList);
var
  t: Char;
  st: string;
  FInt: Integer;
  IntValue: TDxBenInt;
  ListValue: TDxBenList;
  StrValue: TDxBenString;
  DicValue: TDxBenDictionary;
begin
  //开始解析
  while p^ <> ''  do
  begin
    t := P^;
    case t of
    'i':
      begin
        //是一个整数
        Inc(p);
        st := '';
        while p^ <> 'e' do
        begin
          if not CharInSet(p^, ['-','0'..'9']) then
            raise Exception.Create('无效的数据类型');
          st := st   p^;
          Inc(p);
        end;
        if not TryStrToInt(st,FInt) then
          raise Exception.Create('无效的数据类型i' st 'e');
        IntValue := TDxBenInt.Create;
        IntValue.FValue := FInt;
        IntValue.FParent := List;
        List.FList.Add(IntValue);
        Inc(p);
      end;
    'l':
      begin
        //列表
        Inc(p);
        ListValue := TDxBenList.Create;
        ListValue.FParent := List;
        List.FList.Add(ListValue);
        ParserToList(p,ListValue);
      end;
    'd':
      begin
        //字典
        Inc(p);
        DicValue := TDxBenDictionary.Create;
        DicValue.FParent := List;
        List.FList.Add(DicValue);
        ParserToDictionary(p,DicValue);
      end;
    'e': Break;//结束了
    else
      begin
        //字符串
        st := '';
        while p^ <> ':' do
        begin
          if not CharInSet(p^, ['-','0'..'9']) then
            raise Exception.Create('无效的数据类型');
          st := st   p^;
          Inc(p);
        end;
        if not TryStrToInt(st,FInt) then
          raise Exception.Create('无效的数据类型' st);
        //读取字符串
        Inc(p);
        if StrLen(p) < FInt then
          raise Exception.Create('字符串解析长度不够');
        StrValue := TDxBenString.Create;
        SetLength(StrValue.FValue,Fint);
        Move(p^,Pointer(StrValue.FValue)^,FInt*Sizeof(Char));
        StrValue.FParent := List;
        List.FList.Add(StrValue);
        Inc(p,Fint);
      end;
    end;
  end;
end;

function TDxBenDictionary.ToString: string;
begin

end;

{ TDxTorrentFile }

procedure TDxTorrentFile.Clear;
begin
  FDict.Clear;
end;

constructor TDxTorrentFile.Create;
begin
  inherited;
  FDict := TDxBenDictionary.Create;
end;

destructor TDxTorrentFile.Destroy;
begin
  FDict.Free;
  inherited;
end;

function TDxTorrentFile.Getannounce: string;
var
  F: TDxBenValue;
begin
  F := FDict.Values['announce'];
  if F <> nil then
    Result := F.AsString
  else Result := '';
end;

function TDxTorrentFile.Getannounce_list: TDxBenList;
begin
  Result := TDxBenList(FDict.Values['announce-list']);
end;

function TDxTorrentFile.GetBtInfo: TDxBtInfo;
begin
  Result := TDxBtInfo(FDict.Values['info']);
end;

function TDxTorrentFile.GetComment: string;
begin
  if FDict.FDict.ContainsKey('comment') then
  begin
    if CompareText(Encoding,'utf-8') = 0 then
      Result := UTF8Decode(FDict.Values['comment'].AsString)
    else result := FDict.Values['comment'].AsString
  end
  else result := '';
end;

function SpanOfNowAndThen(const ANow, AThen: TDateTime): TDateTime;
begin
  if ANow < AThen then
    Result := AThen - ANow
  else
    Result := ANow - AThen;
end;

function SecondSpan(const ANow, AThen: TDateTime): Double;
begin
  Result := SecsPerDay * SpanOfNowAndThen(ANow, AThen);
end;

function TDxTorrentFile.GetCreateDate: TDateTime;
var
  F: TDxBenValue;
  V: Double;
begin
  F := FDict.Values['creation date'];
  if F <> nil then
  begin                 //是从1970年1月1日00:00:00到现在的秒数
    Result := F.AsInteger;
    //V := StrToDate('1970-01-01');//25569
    V := SecondSpan(Now,25569);
    V := (V - Result) / SecsPerDay;
    Result := Now - V
  end
  else Result := 0;
end;

function TDxTorrentFile.GetCreator: string;
var
  F: TDxBenValue;
begin
  F := FDict.Values['created by'];
  if F <> nil then
    Result := F.AsString
  else Result := '';
end;

function TDxTorrentFile.GetEncoding: string;
begin
  if FDict.Values['encoding'] <> nil then
    Result := FDict.Values['encoding'].AsString
  else result := '';
end;

procedure TDxTorrentFile.LoadFromFile(FileName: string);
var
  F: TFileStream;
begin
  F := TFileStream.Create(FileName,fmOpenRead);
  LoadFromStream(F);
  F.Free;
end;

procedure TDxTorrentFile.LoadFromStream(Stream: TStream);
var
  c: Byte;
begin
  Clear;
  Stream.ReadBuffer(c,1);
  if Char(c) = 'd' then
    ParserStream(Stream,FDict);
end;


procedure TDxTorrentFile.ParserStreamToList(Stream: TStream; List: TDxBenList);
var
  t: Byte;
  st: Ansistring;
  FInt: Integer;
  IntValue: TDxBenInt;
  ListValue: TDxBenList;
  StrValue: TDxBenString;
  DicValue: TDxBenDictionary;
begin
  while Stream.Position <> Stream.Size do
  begin
    Stream.ReadBuffer(t,SizeOf(t));
    case Char(t) of
    'i':
      begin
        //是一个整数
        st := '';
        Stream.ReadBuffer(t,SizeOf(t));
        while Char(t) <> 'e' do
        begin
          if not CharInSet(Char(t), ['-','0'..'9']) then
            raise Exception.Create('无效的数据类型');
          st := st   Char(t);
        end;
        if not TryStrToInt(st,FInt) then
          raise Exception.Create('无效的数据类型i' st 'e');
        IntValue := TDxBenInt.Create;
        IntValue.FValue := FInt;
        IntValue.FParent := List;
        List.FList.Add(IntValue);
      end;
    'l':
      begin
        //列表
        ListValue := TDxBenList.Create;
        ListValue.FParent := List;
        List.FList.Add(ListValue);
        ParserStreamToList(Stream,ListValue);
      end;
    'd':
      begin
        DicValue := TDxBenDictionary.Create;
        DicValue.FParent := List;
        List.FList.Add(DicValue);
        ParserStream(Stream,DicValue);
      end;
    'e': Break;
    else
      begin
        st := '';
        while Char(t) <> ':' do
        begin
          if not CharInSet(Char(t), ['-','0'..'9']) then
            raise Exception.Create('无效的数据类型');
          st := st   Char(t);
          Stream.ReadBuffer(t,SizeOf(t));
        end;
        if not TryStrToInt(st,FInt) then
          raise Exception.Create('无效的数据类型' st);
        //读取字符串
        if Stream.Size - Stream.Position < FInt then
          raise Exception.Create('字符串解析长度不够');
        SetLength(st,Fint);
        Stream.ReadBuffer(Pointer(st)^,Fint);
        StrValue := TDxBenString.Create;
        if CompareText(Encoding,'utf-8') = 0 then
          StrValue.FValue := UTF8Decode(st)
        else StrValue.FValue := st;
        StrValue.FParent := List;
        List.FList.Add(StrValue);
      end;
    end;
  end;
end;

procedure TDxTorrentFile.ParserStream(Stream: TStream;Dict: TDxBenDictionary);
type
  TParserState = (PS_None,PS_Key,PS_Value);
var
  t: Byte;
  st: Ansistring;
  FInt: Integer;
  IntValue: TDxBenInt;
  ListValue: TDxBenList;
  StrValue: TDxBenString;
  DicValue: TDxBenDictionary;
  Parstate: TParserState;
  key: string;
begin
  Parstate := PS_None;
  while Stream.Position < Stream.Size do
  begin
    Stream.ReadBuffer(t,SizeOf(t));
    case Char(t) of
    'i':
      begin
        if Parstate <> PS_Value then
          raise Exception.Create('B编码字典的Key必须是字符串!');
        st := '';
        Stream.ReadBuffer(t,SizeOf(t));
        while Char(t) <> 'e' do
        begin
          if not CharInSet(Char(t), ['-','0'..'9']) then
            raise Exception.Create('无效的数据类型');
          st := st   Char(t);
          Stream.ReadBuffer(t,SizeOf(t));
        end;
        if not TryStrToInt(st,FInt) then
          raise Exception.Create('无效的数据类型i' st 'e');
        IntValue := TDxBenInt.Create;
        IntValue.FValue := FInt;
        IntValue.FParent := Dict;
        Dict.FDict[Key] := IntValue;
        Parstate := PS_None;
      end;
    'l':
      begin
        if Parstate <> PS_Value then
          raise Exception.Create('B编码字典的Key必须是字符串!');
        ListValue := TDxBenList.Create;
        ListValue.FParent := Dict;
        Dict.FDict[Key] := ListValue;
        ParserStreamToList(Stream,ListValue);
        Parstate := PS_None;
      end;
    'd':
      begin
        if Parstate <> PS_Value then
           raise Exception.Create('B编码字典的Key必须是字符串!');
        DicValue := TDxBenDictionary.Create;
        DicValue.FParent := Dict;
        Dict.FDict[Key] := DicValue;
        ParserStream(stream,DicValue);
        Parstate := PS_None;
      end;
    'e':
      begin
        if Parstate = PS_Value then
          Parstate := PS_None
        else if Parstate = PS_None then
          Break;
      end;
    else
      begin
        st := '';
        while Char(t) <> ':' do
        begin
          if not CharInSet(Char(t), ['-','0'..'9']) then
            raise Exception.Create('无效的数据类型');
          st := st   Char(t);
          Stream.ReadBuffer(t,SizeOf(t));
        end;
        if not TryStrToInt(st,FInt) then
          raise Exception.Create('无效的数据类型' st);
        if Stream.Size - Stream.Position < FInt then
          raise Exception.Create('字符串解析长度不够');
        SetLength(st,Fint);
        Stream.ReadBuffer(Pointer(st)^,Fint);
        if Parstate = PS_None then
        begin
          key := st;
          if Dict.FDict.ContainsKey(st) then
            raise Exception.Create('字典存在重复信息');
          Dict.FDict.Add(st,nil);
          Parstate := PS_Value;
        end
        else if Parstate = PS_Value then
        begin
          StrValue := TDxBenString.Create;
          StrValue.FParent := Dict;
          if CompareText(Encoding,'utf-8') = 0 then
            StrValue.FValue := UTF8Decode(st)
          else StrValue.FValue := st;
          Dict.FDict[Key] := StrValue;
          Parstate := PS_None;
        end;
      end;
    end;
  end;
end;

{ TDxBtInfo }

function TDxBtInfo.GetFiles: TDxBenList;
begin
  Result := TDxBenList(Values['files'])
end;

function TDxBtInfo.GetName: string;
var
  F: TDxBenValue;
begin
  F := Values['name'];
  if F <> nil then
    Result := F.AsString
  else Result := '';
end;

function TDxBtInfo.GetNameUtf8: string;
var
  F: TDxBenValue;
begin
  F := Values['name.utf-8'];
  if F <> nil then
    Result := F.AsString
  else Result := '';
end;

function TDxBtInfo.Getpublisher: string;
var
  F: TDxBenValue;
begin
  F := Values['publisher'];
  if F <> nil then
    Result := F.AsString
  else Result := '';
end;

function TDxBtInfo.Getpublisherurl: string;
var
  F: TDxBenValue;
begin
  F := Values['publisher-url'];
  if F <> nil then
    Result := F.AsString
  else Result := '';
end;

function TDxBtInfo.GetpublisherurlUtf8: string;
var
  F: TDxBenValue;
begin
  F := Values['publisher-url.utf8'];
  if F <> nil then
    Result := F.AsString
  else Result := '';
end;

function TDxBtInfo.GetpublisherUtf8: string;
var
  F: TDxBenValue;
begin
  F := Values['publisher.utf-8'];
  if F <> nil then
    Result := F.AsString
  else Result := '';
end;

function TDxBtInfo.GetSingleFile: Boolean;
begin
  Result := Files = nil;
end;

end.

标签: 种子

实例下载地址

bt种子文件解析 含源码下载

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

第 1 楼 why930622 发表于: 2016-09-24 13:35 33
啊啊啊俺看看啊啊啊啊

支持(0) 盖楼(回复)

发表评论

(您的评论需要经过审核才能显示)

查看所有1条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警