基础知识:

torrent文件信息存储格式:

bencoding是一种以简洁格式指定和组织数据的方法。支持下列类型:字节串、整数、列表和字典。

1 字符串存储格式:  <字符串的长度>:<字符串的内容> 
例如:    4:abcd 表示abcd, 2:ab 表示ab

2 数字的存储格式:  i<整数>e
例如:    i32e 表示整数32, i1024e 表示整数1024

3 列表的存储格式: l<子元素>e  其中:子元素可以是字符串,整数,列表和字典,或者是它们的组合体
例如:    l4:asdf4:qwere    表示 [ "asdf", "qwer" ]

4 字典的存储格式: d<<key><value><key><value><key><value>...<key><value>>e 
其中:key只能是字符串类型,value则可以是字符串,整数,列表和字典,或者是它们的组合体,key和value必须是成对出现的
例如:    d3:cow3:moo4:spam4:eggse    表示 { "cow" => "moo", "spam" => "eggs" } 
        d4:spaml1:a1:bee            表示 { "spam" => [ "a", "b" ] } 
        d9:publisher3:bob4:spaml1:a1:be5:counti80ee  表示 { "publisher" => "bob", "spam" => [ "a", "b" ], "count" => 80 }

代码:

 using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using NPOI.OpenXmlFormats.Spreadsheet;
using Newtonsoft.Json; namespace ConsoleApp
{
/// <summary>
/// Summary description for Class1.-change wdq
/// </summary>
public class Class1
{
static void Main(string[] args)
{
if (args.Length != )
{
Console.WriteLine("请指定torrent文件");
return;
}
string filename = args[];
var data = Torrent.DecodeFile(filename);
//Console.WriteLine(JsonConvert.SerializeObject(data, Newtonsoft.Json.Formatting.Indented));
ShowData(data);
} private static void ShowData(ItemBase data)
{
if (data.ItemType == ItemType.Dictionary)
{
foreach (var kv in (data as DictionaryItem).DictionaryData)
{
switch (kv.Value.ItemType)
{
case ItemType.Dictionary:
Console.WriteLine(kv.Key + ":");
ShowData(kv.Value);
break;
case ItemType.List:
Console.WriteLine(kv.Key + ":");
ShowData(kv.Value);
break;
case ItemType.String:
if (kv.Key == "pieces")
{
break;
}
Console.WriteLine(kv.Key + "=" + (kv.Value as StringItem).StringData);
break;
case ItemType.Number:
Console.WriteLine(kv.Key + "=" + (kv.Value as NumberItem).NumberData);
break;
}
}
}
if (data.ItemType == ItemType.List)
{
foreach (var i in (data as ListItem).ListData)
{
switch (i.ItemType)
{
case ItemType.Dictionary:
case ItemType.List:
ShowData(i);
break;
case ItemType.String:
Console.WriteLine((i as StringItem).StringData);
break;
case ItemType.Number:
Console.WriteLine((i as NumberItem).NumberData);
break;
}
}
}
}
} public class Torrent
{
public static ItemBase DecodeFile(string filename)
{
using (var fs = new FileStream(filename, FileMode.Open))
{
using (BinaryReader br = new BinaryReader(fs))
{
return DecodeData(br);
}
}
} private static ItemBase DecodeData(BinaryReader br, Stack<bool> st = null)
{
var flag = br.PeekChar();
List<byte> ls = new List<byte>();
byte b = ;
switch (flag)
{
case 'e':
br.ReadByte();
return null;
case 'l'://列表
br.ReadByte();
var itemLs = new ListItem();
ItemBase i = null;
if (st == null)
{
st = new Stack<bool>();
}
st.Push(true);
do
{
i = DecodeData(br, new Stack<bool>());
if (i != null)
{
itemLs.ListData.Add(i);
}
else
{
st.Pop();
}
} while (st.Count != && br.BaseStream.Position != br.BaseStream.Length); return itemLs;
case 'd'://字典
br.ReadByte();
var itemDic = new DictionaryItem();
var key = DecodeData(br);
while (key != null && br.BaseStream.Position != br.BaseStream.Length)
{
var val = DecodeData(br);
itemDic.DictionaryData[(key as StringItem).StringData] = val;
key = DecodeData(br);
} return itemDic;
case 'i'://数字
br.ReadByte();
b = br.ReadByte();
while (b != 'e')
{
ls.Add(b);
b = br.ReadByte();
}
return new NumberItem(long.Parse(Encoding.UTF8.GetString(ls.ToArray()))) { RawBytes = ls.ToArray() };
default://字符串
b = br.ReadByte();
while (b != ':')
{
ls.Add(b);
b = br.ReadByte();
}
var len = int.Parse(Encoding.UTF8.GetString(ls.ToArray()));
var bufStr = br.ReadBytes(len);
var data = Encoding.UTF8.GetString(bufStr);
return new StringItem(data) { RawBytes = bufStr };
}
}
} public class ItemBase
{
[JsonIgnore]
public ItemType ItemType { get; set; }
[JsonIgnore]
public byte[] RawBytes { get; set; }
} public class StringItem : ItemBase
{
public StringItem(string data)
{
StringData = data;
ItemType = ItemType.String;
}
public string StringData { get; set; }
}
public class NumberItem : ItemBase
{
public NumberItem(long num)
{
NumberData = num;
ItemType = ItemType.Number;
}
public long NumberData { get; set; }
} public class ListItem : ItemBase
{
public ListItem()
{
ItemType = ItemType.List;
}
public List<ItemBase> ListData { get; set; } = new List<ItemBase>();
} public class DictionaryItem : ItemBase
{
public DictionaryItem()
{
ItemType = ItemType.Dictionary;
}
public Dictionary<string, ItemBase> DictionaryData { get; set; } = new Dictionary<string, ItemBase>();
} public enum ItemType
{
String, Number, List, Dictionary
}
}

Github地址:https://github.com/a14907/AConsoleAppForFun.git

  效果:

C# 解析torrent文件的更多相关文章

  1. Torrent文件的解析与转换

    Torrent简介 BitTorrent协议的种子文件(英语:Torrent file)可以保存一组文件的元数据.这种格式的文件被BitTorrent协议所定义.扩展名一般为".torren ...

  2. Android 解析XML文件和生成XML文件

    解析XML文件 public static void initXML(Context context) { //can't create in /data/media/0 because permis ...

  3. CSharpGL(9)解析OBJ文件并用CSharpGL渲染

    CSharpGL(9)解析OBJ文件并用CSharpGL渲染 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码中包含10多个独立的Demo ...

  4. Jsoup系列学习(2)-解析html文件

    解析html文件 1.当我们通过发送http请求时,有时候返回结果是一个html格式字符串,你需要从一个网站获取和解析一个HTML文档,并查找其中的相关数据.你可以使用下面解决方法: 使用 Jsoup ...

  5. JAVA使用SAX解析XML文件

    在我的另一篇文章(http://www.cnblogs.com/anivia/p/5849712.html)中,通过一个例子介绍了使用DOM来解析XML文件,那么本篇文章通过相同的XML文件介绍如何使 ...

  6. JAVA中使用DOM解析XML文件

    XML是一种方便快捷高效的数据保存传输的格式,在JSON广泛使用之前,XML是服务器和客户端之间数据传输的主要方式.因此,需要使用各种方式,解析服务器传送过来的信息,以供使用者查看. JAVA作为一种 ...

  7. CSharpGL(5)解析3DS文件并用CSharpGL渲染

    CSharpGL(5)解析3DS文件并用CSharpGL渲染 我曾经写过一个简单的*.3ds文件的解析器,但是只能解析最基本的顶点.索引信息,且此解析器是仿照别人的C++代码改写的,设计的也不好,不方 ...

  8. php解析.csv文件

    public function actionImport() { //post请求过来的 $fileName = $_FILES['file']['name']; $fileTmpName = $_F ...

  9. java中采用dom4j解析xml文件

    一.前言 在最近的开发中用到了dom4j来解析xml文件,以前听说过来解析xml文件的几种标准方式:但是从来的没有应用过来,所以可以在google中搜索dmo4j解析xml文件的方式,学习一下dom4 ...

随机推荐

  1. AI 学习路线

    [导读] 本文由知名开源平台,AI技术平台以及领域专家:Datawhale,ApacheCN,AI有道和黄海广博士联合整理贡献,内容涵盖AI入门基础知识.数据分析挖掘.机器学习.深度学习.强化学习.前 ...

  2. 初识gauge自动化测试框架(二)

    看到一些同学对该工具有点一兴趣,那么我将继续介绍Gauge自动化测试工具. Gauge本质上一个BDD(Behavior Driven Development)测试框架.所以,首先你要了解BDD的操作 ...

  3. redis 的过期策略都有哪些?内存淘汰机制都有哪些?

    面试题 redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现? 面试官心理分析 如果你连这个问题都不知道,上来就懵了,回答不出来,那线上你写代码的时候,想当然的认为写进 r ...

  4. 使用Harbor配置Kubernetes私有镜像仓库

    通常情况下,在私有云环境中使用kubernetes时,我们要从docker registry拉取镜像的时候,都会给docker daemo配置–insecure-registry属性来告诉docker ...

  5. phpcms不能批量更新栏目页和内容页

    需要给网站根目录更加users用户的写入权限.

  6. MR-join连接1......

    MR-join连接

  7. Docker版本与安装介绍

    Docker版本与安装介绍 Docker-CE 和 Docker-EE Centos 上安装 Docker-CE Ubuntu 上安装 Docker-CE Docker-CE和Docker-EE Do ...

  8. vue scoped >>> & git conflict <<<<<<< HEAD

    vue scoped >>> & git conflict <<<<<<< HEAD Q: ???还有这操作 A: > > ...

  9. XPath、CSS 选择器 -学习地址

    http://www.w3school.com.cn/cssref/css_selectors.asp http://www.w3school.com.cn/xpath/xpath_syntax.as ...

  10. Java中的Null是什么?

    对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NPE)的骚扰.连Java的发明者都承认这是他的一项巨大失误.Java为什么要保留null呢?null出现有一段时间了,并且我认 ...