C# 解析bt种子

来源:互联网 发布:spark kmeans java 编辑:程序博客网 时间:2024/04/28 21:18
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(1970, 1, 1, 0, 0, 0);private long _codePage = 0;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 = 0;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, 0, buffer.Length);torrentFile.Close();     if ((char)buffer[0] != 'd'){if (OpenError.Length == 0) OpenError = "错误的Torrent文件,开头第1字节不是100";return;}GetTorrentData(buffer);}     #region 开始读数据     /// <summary>/// 开始读取/// </summary>/// <param name="buffer"></param>private void GetTorrentData(byte[] buffer){int startIndex = 1;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 = 0;ArrayList _tempList = GetKeyData(buffer, ref starIndex, ref listCount);for (int i = 0; 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 == 0) 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 == 0) 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 = 0;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 == 0) 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 = 0;ArrayList _nodesList = GetKeyData(buffer, ref starIndex, ref nodesCount);int ipCount = _nodesList.Count / 2;for (int i = 0; i != ipCount; i++){Notes.Add(_nodesList[i * 2] + ":" + _nodesList[(i * 2) + 1]);}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, 1);switch (textStar){case "l":starIndex++;listCount++;break;case "e":listCount--;starIndex++;if (listCount == 0) 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 == 0){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 = 0;int leftNumb = 0;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 + 1;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, 1) == "i"){int numb = 0;for (int i = startIndex; i != buffer.Length; i++){if ((char)buffer[i] == 'e') break;numb++;}startIndex++;long retNumb = 0;try{retNumb = long.Parse(System.Text.Encoding.UTF8.GetString(buffer, startIndex, numb - 1));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 = 0;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 + 1;System.IO.MemoryStream keyMemory = new System.IO.MemoryStream(buffer, startIndex, readNumb);byte[] keyBytes = new byte[readNumb];keyMemory.Read(keyBytes, 0, 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, 1);     switch (TextStar){case "l":startIndex++;listCount++;break;case "e":listCount--;startIndex++;if (listCount == 1) FileList.Add(info);if (listCount == 0) 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 = 0;ArrayList PathList = GetKeyData(buffer, ref startIndex, ref PathCount);string Temp = "";for (int i = 0; i != PathList.Count; i++){if (i < PathList.Count && i != 0)Temp += "\\";Temp += PathList[i].ToString();}info.Path = Temp;break;case "PATH.UTF-8":int pathUtf8Count = 0;ArrayList pathutf8List = GetKeyData(buffer, ref startIndex, ref pathUtf8Count);string utfTemp = "";for (int i = 0; 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 = 0;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

原创粉丝点击