C# 解析bt种子
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections; namespace XunleiHelper
{
public class Torrent
{
#region 私有字段
private string _openError = "";
private bool _openFile = false; private string _announce = "";
private IList<string> _announceList = new List<string>();
private DateTime _createTime = new DateTime(, , , , , );
private long _codePage = ;
private string _comment = "";
private string _createdBy = "";
private string _encoding = "";
private string _commentUTF8 = "";
private IList<FileInfo> _fileList = new List<FileInfo>();
private string _name = "";
private string _nameUTF8 = "";
private long _pieceLength = ;
private byte[] _pieces;
private string _publisher = "";
private string _publisherUTF8 = "";
private string _publisherUrl = "";
private string _publisherUrlUTF8 = "";
private IList<string> _notes = new List<string>();
private long _totalLength; #endregion #region 属性
/// <summary>
/// 错误信息
/// </summary>
public string OpenError { set { _openError = value; } get { return _openError; } }
/// <summary>
/// 是否正常打开文件
/// </summary>
public bool OpenFile { set { _openFile = value; } get { return _openFile; } }
/// <summary>
/// 服务器的URL(字符串)
/// </summary>
public string Announce { set { _announce = value; } get { return _announce; } }
/// <summary>
/// 备用tracker服务器列表(列表)
/// </summary>
public IList<string> AnnounceList { set { _announceList = value; } get { return _announceList; } }
/// <summary>
/// 种子创建的时间,Unix标准时间格式,从1970 1月1日 00:00:00到创建时间的秒数(整数)
/// </summary>
public DateTime CreateTime { set { _createTime = value; } get { return _createTime; } }
/// <summary>
/// 未知数字CodePage
/// </summary>
public long CodePage { set { _codePage = value; } get { return _codePage; } }
/// <summary>
/// 种子描述
/// </summary>
public string Comment { set { _comment = value; } get { return _comment; } }
/// <summary>
/// 编码方式
/// </summary>
public string CommentUTF8 { set { _commentUTF8 = value; } get { return _commentUTF8; } }
/// <summary>
/// 创建人
/// </summary>
public string CreatedBy { set { _createdBy = value; } get { return _createdBy; } }
/// <summary>
/// 编码方式
/// </summary>
public string Encoding { set { _encoding = value; } get { return _encoding; } }
/// <summary>
/// 文件信息
/// </summary>
public IList<FileInfo> FileList { set { _fileList = value; } get { return _fileList; } }
/// <summary>
/// 种子名
/// </summary>
public string Name { set { _name = value; } get { return _name; } }
/// <summary>
/// 种子名UTF8
/// </summary>
public string NameUTF8 { set { _nameUTF8 = value; } get { return _nameUTF8; } }
/// <summary>
/// 每个块的大小,单位字节(整数)
/// </summary>
public long PieceLength { set { _pieceLength = value; } get { return _pieceLength; } }
/// <summary>
/// 每个块的20个字节的SHA1 Hash的值(二进制格式)
/// </summary>
private byte[] Pieces { set { _pieces = value; } get { return _pieces; } }
/// <summary>
/// 出版
/// </summary>
public string Publisher { set { _publisher = value; } get { return _publisher; } }
/// <summary>
/// 出版UTF8
/// </summary>
public string PublisherUTF8 { set { _publisherUTF8 = value; } get { return _publisherUTF8; } }
/// <summary>
/// 出版地址
/// </summary>
public string PublisherUrl { set { _publisherUrl = value; } get { return _publisherUrl; } }
/// <summary>
/// 出版地址
/// </summary>
public string PublisherUrlUTF8 { set { _publisherUrlUTF8 = value; } get { return _publisherUrlUTF8; } }
/// <summary>
/// NODES
/// </summary>
public IList<string> Notes { set { _notes = value; } get { return _notes; } } /// <summary>
/// 包含文件的总长度
/// </summary>
public long TotalLength
{
get
{
return _totalLength;
}
} #endregion public Torrent(string fileName)
{
System.IO.FileStream torrentFile = new System.IO.FileStream(fileName, System.IO.FileMode.Open);
byte[] buffer = new byte[torrentFile.Length];
torrentFile.Read(buffer, , buffer.Length);
torrentFile.Close(); if ((char)buffer[] != 'd')
{
if (OpenError.Length == ) OpenError = "错误的Torrent文件,开头第1字节不是100";
return;
}
GetTorrentData(buffer);
} #region 开始读数据 /// <summary>
/// 开始读取
/// </summary>
/// <param name="buffer"></param>
private void GetTorrentData(byte[] buffer)
{
int startIndex = ;
while (true)
{
object Keys = GetKeyText(buffer, ref startIndex);
if (Keys == null)
{
if (startIndex >= buffer.Length) OpenFile = true;
break;
} if (GetValueText(buffer, ref startIndex, Keys.ToString().ToUpper()) == false) break;
}
} #endregion /// <summary>
/// 读取结构
/// </summary>
/// <param name="buffer"></param>
/// <param name="starIndex"></param>
/// <param name="key"></param>
/// <returns></returns>
private bool GetValueText(byte[] buffer, ref int starIndex, string key)
{
switch (key)
{
case "ANNOUNCE":
Announce = GetKeyText(buffer, ref starIndex).ToString();
break;
case "ANNOUNCE-LIST":
int listCount = ;
ArrayList _tempList = GetKeyData(buffer, ref starIndex, ref listCount);
for (int i = ; i != _tempList.Count; i++)
{
AnnounceList.Add(_tempList[i].ToString());
}
break;
case "CREATION DATE":
object date = GetKeyNumb(buffer, ref starIndex).ToString();
if (date == null)
{
if (OpenError.Length == ) OpenError = "CREATION DATE 返回不是数字类型";
return false;
}
CreateTime = CreateTime.AddTicks(long.Parse(date.ToString()));
break;
case "CODEPAGE":
object codePageNumb = GetKeyNumb(buffer, ref starIndex);
if (codePageNumb == null)
{
if (OpenError.Length == ) OpenError = "CODEPAGE 返回不是数字类型";
return false;
}
CodePage = long.Parse(codePageNumb.ToString());
break;
case "ENCODING":
Encoding = GetKeyText(buffer, ref starIndex).ToString();
break;
case "CREATED BY":
CreatedBy = GetKeyText(buffer, ref starIndex).ToString();
break;
case "COMMENT":
Comment = GetKeyText(buffer, ref starIndex).ToString();
break;
case "COMMENT.UTF-8":
CommentUTF8 = GetKeyText(buffer, ref starIndex).ToString();
break;
case "INFO":
int fileListCount = ;
GetFileInfo(buffer, ref starIndex, ref fileListCount);
break;
case "NAME":
Name = GetKeyText(buffer, ref starIndex).ToString();
break;
case "NAME.UTF-8":
NameUTF8 = GetKeyText(buffer, ref starIndex).ToString();
break;
case "PIECE LENGTH":
object pieceLengthNumb = GetKeyNumb(buffer, ref starIndex);
if (pieceLengthNumb == null)
{
if (OpenError.Length == ) OpenError = "PIECE LENGTH 返回不是数字类型";
return false;
}
PieceLength = long.Parse(pieceLengthNumb.ToString());
break;
case "PIECES":
Pieces = GetKeyByte(buffer, ref starIndex);
break;
case "PUBLISHER":
Publisher = GetKeyText(buffer, ref starIndex).ToString();
break;
case "PUBLISHER.UTF-8":
PublisherUTF8 = GetKeyText(buffer, ref starIndex).ToString();
break;
case "PUBLISHER-URL":
PublisherUrl = GetKeyText(buffer, ref starIndex).ToString();
break;
case "PUBLISHER-URL.UTF-8":
PublisherUrlUTF8 = GetKeyText(buffer, ref starIndex).ToString();
break;
case "NODES":
int nodesCount = ;
ArrayList _nodesList = GetKeyData(buffer, ref starIndex, ref nodesCount);
int ipCount = _nodesList.Count / ;
for (int i = ; i != ipCount; i++)
{
Notes.Add(_nodesList[i * ] + ":" + _nodesList[(i * ) + ]);
}
break; default:
return false;
}
return true;
} #region 获取数据
/// <summary>
/// 获取列表方式 "I1:Xe"="X" 会调用GetKeyText
/// </summary>
/// <param name="buffer"></param>
/// <param name="starIndex"></param>
/// <param name="listCount"></param>
private ArrayList GetKeyData(byte[] buffer, ref int starIndex, ref int listCount)
{
ArrayList _tempList = new ArrayList();
while (true)
{
string textStar = System.Text.Encoding.UTF8.GetString(buffer, starIndex, );
switch (textStar)
{
case "l":
starIndex++;
listCount++;
break;
case "e":
listCount--;
starIndex++;
if (listCount == ) return _tempList;
break;
case "i":
_tempList.Add(GetKeyNumb(buffer, ref starIndex).ToString());
break;
default:
object listText = GetKeyText(buffer, ref starIndex);
if (listText != null)
{
_tempList.Add(listText.ToString());
}
else
{
if (OpenError.Length == )
{
OpenError = "错误的Torrent文件,ANNOUNCE-LIST错误";
return _tempList;
}
}
break;
}
}
}
/// <summary>
/// 获取字符串
/// </summary>
/// <param name="buffer"></param>
/// <param name="startIndex"></param>
/// <returns></returns>
private object GetKeyText(byte[] buffer, ref int startIndex)
{
int numb = ;
int leftNumb = ;
for (int i = startIndex; i != buffer.Length; i++)
{
if ((char)buffer[i] == ':') break;
if ((char)buffer[i] == 'e')
{
leftNumb++;
continue;
}
numb++;
} startIndex += leftNumb;
string textNumb = System.Text.Encoding.UTF8.GetString(buffer, startIndex, numb);
try
{
int readNumb = Int32.Parse(textNumb);
startIndex = startIndex + numb + ;
object keyText = System.Text.Encoding.UTF8.GetString(buffer, startIndex, readNumb);
startIndex += readNumb;
return keyText;
}
catch
{
return null;
} } /// <summary>
/// 获取数字
/// </summary>
/// <param name="buffer"></param>
/// <param name="startIndex"></param>
private object GetKeyNumb(byte[] buffer, ref int startIndex)
{
if (System.Text.Encoding.UTF8.GetString(buffer, startIndex, ) == "i")
{
int numb = ;
for (int i = startIndex; i != buffer.Length; i++)
{
if ((char)buffer[i] == 'e') break;
numb++;
}
startIndex++;
long retNumb = ;
try
{
retNumb = long.Parse(System.Text.Encoding.UTF8.GetString(buffer, startIndex, numb - ));
startIndex += numb;
return retNumb;
}
catch
{
return null;
}
}
else
{
return null;
} } /// <summary>
/// 获取BYTE数据
/// </summary>
/// <param name="buffer"></param>
/// <param name="startIndex"></param>
/// <returns></returns>
private byte[] GetKeyByte(byte[] buffer, ref int startIndex)
{
int numb = ;
for (int i = startIndex; i != buffer.Length; i++)
{
if ((char)buffer[i] == ':') break;
numb++;
}
string textNumb = System.Text.Encoding.UTF8.GetString(buffer, startIndex, numb); try
{
int readNumb = Int32.Parse(textNumb);
startIndex = startIndex + numb + ;
System.IO.MemoryStream keyMemory = new System.IO.MemoryStream(buffer, startIndex, readNumb);
byte[] keyBytes = new byte[readNumb];
keyMemory.Read(keyBytes, , readNumb);
keyMemory.Close();
startIndex += readNumb;
return keyBytes;
}
catch
{
return null;
}
} /// <summary>
/// 对付INFO的结构
/// </summary>
/// <param name="buffer"></param>
/// <param name="startIndex"></param>
/// <param name="listCount"></param>
private void GetFileInfo(byte[] buffer, ref int startIndex, ref int listCount)
{
if ((char)buffer[startIndex] != 'd') return;
startIndex++; if (GetKeyText(buffer, ref startIndex).ToString().ToUpper() == "FILES")
{
FileInfo info = new FileInfo(); while (true)
{
string TextStar = System.Text.Encoding.UTF8.GetString(buffer, startIndex, ); switch (TextStar)
{
case "l":
startIndex++;
listCount++;
break;
case "e":
listCount--;
startIndex++;
if (listCount == ) FileList.Add(info);
if (listCount == ) return;
break;
case "d":
info = new FileInfo();
listCount++;
startIndex++;
break; default:
object listText = GetKeyText(buffer, ref startIndex);
if (listText == null) return;
switch (listText.ToString().ToUpper()) //转换为大写
{
case "ED2K":
info.De2K = GetKeyText(buffer, ref startIndex).ToString();
break;
case "FILEHASH":
info.FileHash = GetKeyText(buffer, ref startIndex).ToString();
break; case "LENGTH":
info.Length = Convert.ToInt64(GetKeyNumb(buffer, ref startIndex));
_totalLength += info.Length;
break;
case "PATH":
int PathCount = ;
ArrayList PathList = GetKeyData(buffer, ref startIndex, ref PathCount);
string Temp = "";
for (int i = ; i != PathList.Count; i++)
{
if (i < PathList.Count && i != )
Temp += "\\";
Temp += PathList[i].ToString();
}
info.Path = Temp;
break;
case "PATH.UTF-8":
int pathUtf8Count = ;
ArrayList pathutf8List = GetKeyData(buffer, ref startIndex, ref pathUtf8Count);
string utfTemp = "";
for (int i = ; i != pathutf8List.Count; i++)
{
utfTemp += pathutf8List[i].ToString();
}
info.PathUTF8 = utfTemp;
break;
}
break;
} } }
} #endregion /// <summary>
/// 对应结构 INFO 多个文件时
/// </summary>
public class FileInfo
{
private string path = "";
private string pathutf8 = "";
private long length = ;
private string md5sum = "";
private string de2k = "";
private string filehash = ""; /// <summary>
/// 文件路径
/// </summary>
public string Path { get { return path; } set { path = value; } }
/// <summary>
/// UTF8的名称
/// </summary>
public string PathUTF8 { get { return pathutf8; } set { pathutf8 = value; } }
/// <summary>
/// 文件大小
/// </summary>
public long Length { get { return length; } set { length = value; } }
/// <summary>
/// MD5验效 (可选)
/// </summary>
public string MD5Sum { get { return md5sum; } set { md5sum = value; } }
/// <summary>
/// ED2K 未知
/// </summary>
public string De2K { get { return de2k; } set { de2k = value; } }
/// <summary>
/// FileHash 未知
/// </summary>
public string FileHash { get { return filehash; } set { filehash = value; } }
}
}
}
扩展阅读:b编码级种子文件的解析
En解释+API:http://wiki.theory.org/BitTorrentSpecification (推荐LordMike所写的库:下载)
原文:http://hi.baidu.com/kongfl888/item/6c97d4cb14a35b42a8ba94f8
C# 解析bt种子的更多相关文章
- [搜片神器]使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)
谢谢园子朋友的支持,已经找到个VPS进行测试,国外的服务器:http://www.sosobta.com 大家可以给提点意见... 出售商业网站代码,万元起,非诚勿扰,谢谢. 联系h31h31 a ...
- 使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)
使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源) 先直接上程序界面,了解整体工作流程是什么样子的,求服务器进行挂机测试,需要固定IP,空间大概需要10G左右(主要是BT种子占用空间 ...
- java 解析/读取 种子/bt/torrent 内容
碰到不会的技术问题,我还是先度娘.能中文看懂,为什么非要看英文呢. java 解析/读取 种子/bt/torrent 内容,这个度娘给的满意答案并不是很多.GG之后的搜索结果出现了stackover ...
- [搜片神器]直接从DHT网络下载BT种子的方法
DHT抓取程序开源地址:https://github.com/h31h31/H31DHTDEMO 数据处理程序开源地址:https://github.com/h31h31/H31DHTMgr DHT系 ...
- bt 介绍以及 bt 种子的hash值(特征值)计算
bt种子的hansh值计算,近期忽然对bt种子感兴趣了(原因勿问) 1. bt种子(概念) bt 是一个分布式文件分发协议,每一个文件下载者在下载的同一时候向其他下载者不断的上传已经下载的数据,这样保 ...
- 据磁力链获得BT种子
最近研究了一下磁力链magnet和BT种子torrent文件之间的相互转换.其实通过torrent文件获得磁力链实现起来比较简单,但反过来并非是一个可逆的过程,磁力链转BT种子理论上来说是不可能实现的 ...
- [搜片神器]BT种子下载超时很多的问题分析
继续接着第一篇写:使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)[搜片神器] 谢谢园子朋友的支持,已经找到个VPS进行测试,国外的服务器: h31bt.org 大家可以给提点意 ...
- bt种子文件文件结构
估计80%以上接触互联网的人都知道bt是什么东西,任何一个用bt下载的人都知道这样一个概念,种子.bt种子就是记录了p2p对等网络中tracker, nodes, files等信息,也就是说,这个 ...
- [放松一下] 经典高清电影合集 170G BT种子下载
经典高清电影合集 170G BT种子下载 点击文件名下载 经典高清电影合集170G BT种子.torrent 下载方法 经典高清电影合集详情见目录: 1. 杀手47 2. 这个杀手不太冷 3. 放牛班 ...
随机推荐
- weighted Kernel k-means 加权核k均值算法理解及其实现(一)
那就从k-means开始吧 对于机器学习的新手小白来说,k-means算法应该都会接触到吧.传统的k-means算法是一个硬聚类(因为要指定k这个参数啦)算法.这里利用百度的解释 它是数据点到原型的某 ...
- Struts1项目转成Struts2项目步奏
注意:要转成Struts2必须struts2配置和流程理解,我不知道,我只能说还是知道struts2然后转成struts2对. 1.先备份一份.不要没转成功项目搞蹦了都回不来了. 2.导入Struts ...
- Mac周边环境 goBASIC语言HelloWorld
1. 安装mercurial Mercurial 是一种轻量级分布式版本号控制系统,採用 Python 语言实现 能够输入hg命令查询系统是否安装mercurial,能够例如以下两种命令安装 $sud ...
- linux 文件系统解析及相关命令(转)
简介 文件系统就是分区或磁盘上的所有文件的逻辑集合. 文件系统不仅包含着文件中的数据而且还有文件系统的结构,所有Linux 用户和程序看到的文件.目录.软连接及文件保护信息等都存储在其中. 不同Lin ...
- Qt原始资源形象问题后删除
这些天Qt请项目超市收银系统,作为练一练手,无论如何,亦休闲亦无关,做几乎同样的.旨在取代以前的资源图片, 是什么改变了,码里面的路径都改了.还是编译只是去,总是提示这样一个错误. <s ...
- HTML基金会2----联系,像, 第,对齐
ios讨论组1团:135718460 在web开发中.排版,布局非常重要,因此我们要把基础的东西打坚固,大家不要 慌,慢慢来. 直接把代码拿过去,直接就能够执行的. 1.标题 2.段落 3.HTML ...
- Javascript中的深拷贝和浅拷贝
var obj = { a:1, arr: [1,2] }; var obj1 = obj; //浅复制 var obj2 = deepCopy(obj); //深复制 javascript中创建对象 ...
- cer证书签名验证
一个cer还需要一个签名的证书本身,这是为了防止cer证书被篡改. 有两种类型的证书: 1. 根证书 2. 由根证书颁发子证书. 特根证书.它是自签名. 而其它子证书的签名公钥都保存在它的上级证书里面 ...
- python test0729.py
#!/usr/env python #-*- coding: utf-8 -*- import urllib import urllib2 import random import requests ...
- 无废话WCF入门教程四[WCF的配置文件]
一.概述 配置也是WCF编程中的主要组成部分.在以往的.net应用程序中,我们会把DBConn和一些动态加载类及变量写在配置文件里.但WCF有所不同.他指定向客户端公开的服务,包括服务的地址.服务用于 ...