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种子的更多相关文章

  1. [搜片神器]使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)

    谢谢园子朋友的支持,已经找到个VPS进行测试,国外的服务器:http://www.sosobta.com   大家可以给提点意见... 出售商业网站代码,万元起,非诚勿扰,谢谢. 联系h31h31 a ...

  2. 使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)

    使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源) 先直接上程序界面,了解整体工作流程是什么样子的,求服务器进行挂机测试,需要固定IP,空间大概需要10G左右(主要是BT种子占用空间 ...

  3. java 解析/读取 种子/bt/torrent 内容

    碰到不会的技术问题,我还是先度娘.能中文看懂,为什么非要看英文呢. java 解析/读取 种子/bt/torrent  内容,这个度娘给的满意答案并不是很多.GG之后的搜索结果出现了stackover ...

  4. [搜片神器]直接从DHT网络下载BT种子的方法

    DHT抓取程序开源地址:https://github.com/h31h31/H31DHTDEMO 数据处理程序开源地址:https://github.com/h31h31/H31DHTMgr DHT系 ...

  5. bt 介绍以及 bt 种子的hash值(特征值)计算

    bt种子的hansh值计算,近期忽然对bt种子感兴趣了(原因勿问) 1. bt种子(概念) bt 是一个分布式文件分发协议,每一个文件下载者在下载的同一时候向其他下载者不断的上传已经下载的数据,这样保 ...

  6. 据磁力链获得BT种子

    最近研究了一下磁力链magnet和BT种子torrent文件之间的相互转换.其实通过torrent文件获得磁力链实现起来比较简单,但反过来并非是一个可逆的过程,磁力链转BT种子理论上来说是不可能实现的 ...

  7. [搜片神器]BT种子下载超时很多的问题分析

    继续接着第一篇写:使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)[搜片神器] 谢谢园子朋友的支持,已经找到个VPS进行测试,国外的服务器: h31bt.org  大家可以给提点意 ...

  8. bt种子文件文件结构

      估计80%以上接触互联网的人都知道bt是什么东西,任何一个用bt下载的人都知道这样一个概念,种子.bt种子就是记录了p2p对等网络中tracker, nodes, files等信息,也就是说,这个 ...

  9. [放松一下] 经典高清电影合集 170G BT种子下载

    经典高清电影合集 170G BT种子下载 点击文件名下载 经典高清电影合集170G BT种子.torrent 下载方法 经典高清电影合集详情见目录: 1. 杀手47 2. 这个杀手不太冷 3. 放牛班 ...

随机推荐

  1. Team Foundation Server 2015使用教程--默认团队checkin权限修改

  2. hdu3836联通的强还原性点

    Equivalent Sets Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 104857/104857 K (Java/Other ...

  3. C++它 typedef void *HANDLE

    阅读时编写代码的代码,经常看到一个代码: typedef void *HANDLE ,这是它背后的故事?怎么理解呢? 不明白的时候.这是非常美妙的感觉,后来我才知道这,这是typedef定义,就在vo ...

  4. SQLserver创建与主外键的看法

    一个.背景 最初研究的相关内容数据库.仅仅是正式.从来没有练过,只能慢慢漂流,现在做的客房时,,非常多的知识需要使用视图,慢的实践. 视图:我理解的就是一张表.它把我们所须要的某个表或某几个表中的部分 ...

  5. Unity3D 如何图形问题修正旋转模型已导入?

     如何纠正旋转模型被导入? 一些立体艺术资源包导出其模式,以便 Z 轴向上.Unity 大多数标准的脚本中假定的三维世界 Y 轴代表了.在 Unity 比改动脚本使其契合easy得多. Z 轴朝上 ...

  6. Ubuntu 中查看内核版本和系统版本的三个命令

    一.查看内核版本:cat /proc/version 二.查看内核版本:uname -a 三.查看系统版本:lsb_release -a 四.查看发行版类型:cat /etc/issue

  7. 第8章 装饰模式(Decorator Pattern)

    原文 第8章 装饰模式(Decorator Pattern) 概述: 装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. ...

  8. 1023 Train Problem II(卡特兰数)

    Problem Description As we all know the Train Problem I, the boss of the Ignatius Train Station want ...

  9. hdu 质方数

    Problem Description   小明天生对数字比较敏感,3岁的时候就能背诵圆周率一百位. 现在,小明慢慢长大了,但依然很喜欢数字,最近,他迷上了质数和平方数,并且自己把质数的平方命名为“质 ...

  10. python_基础学习_01_按行读取文件的最优方法

    python 按行读取文件 ,网上搜集有N种方法,效率有区别,先mark最优答案,下次补充测试数据 with open('filename') as file: for line in file: d ...