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. 放牛班 ...
随机推荐
- cocos2d-x3.x屏蔽遮罩层屏蔽触摸button
cocos2d-x3.x触摸方法改变后,.屏蔽掉的层实际上触摸事件的非常easy,首先touchbegan一定要回true,第二,该事件被设定为听吞没触摸true.最近登录触摸水平必须低于0,现在,我 ...
- 小丁带你走进git的世界三-撤销修改(转)
一.撤销指令 git checkout还原工作区的功能 git reset 还原暂存区的功能 git clean 还没有被添加进暂存区的文件也就是git还没有跟踪的文件可以使用这个命令清除他们 g ...
- Java达到MySQL数据库备份(两)
博客<Java实现MySQL数据库备份(一)>使用I/O流的方式实现了MySQL数据库的备份,这样的方法比較繁杂.以下介绍还有一种备份MySQL数据库的方法: import java.io ...
- SQL Server审计功能入门:CDC(Change Data Capture)
原文:SQL Server审计功能入门:CDC(Change Data Capture) 介绍 SQL Server 2008引入了CDC(Change Data Capture),它能记录: 1. ...
- POSIX 螺纹具体解释(1-概要)
线程是有趣的 线程类似于进程.如同进程,线程由内核按时间分片进行管理.在单处理器系统中,内核使用时间分片来模拟线程的并发运行.这样的方式和进程的同样. 而在多处理器系统中,如同多个进程.线程实际上一样 ...
- 基于NSIS脚本开发的安装程序制作软件:易量安装
原文 基于NSIS脚本开发的安装程序制作软件:易量安装 前几天“萝卜”给我推荐了一款安装程序制作工具——易量安装. 易量安装是一款安装程序制作软件,基于著名的NSIS(Nullsoft Scripta ...
- [Tool]利用Advanced Installer建立x86/x64在一起的安装程式
原文 [Tool]利用Advanced Installer建立x86/x64在一起的安装程式 之前使用InstallShield做安装程式时,如果要将程式放在Program Files的话,需要分别针 ...
- hdu 4115 石头剪子布(2-sat问题)
/* 意甲冠军:石头剪子布,目前已知n周围bob会有什么,对alice限制.供u,v,w:设w=0说明a,b回合必须出的一样 否则,必须不一样.alice假设输一回合就输了,否则就赢了 解: 2-sa ...
- XP下类似%windir% %userprofile% 的变量的说明(转)
在一些批处理或者系统技巧操作教程文章中,我们常常会看到一些形如 %windir% 或者 %systemdrive% 的变量.这些变量都代表着什么含义呢?下面小技巧之家为大家整理了在Windows XP ...
- 【 D3.js 入门系列 --- 9.1 】 生产饼图
我个人的博客: www.ourd3js.com csdn博客为: blog.csdn.net/lzhlzz 转载请注明出处.谢谢. 这一节用 Layout 做一个饼状图.第9节中说过, Layout ...