BEncoding的编码与解码

 

1. BEncoding规则

BEncoding是BitTorrent用在传输数据结构的编码方式,我们最熟悉的“种子”文件,它里面的元数据就是 BEncoding 过的字典表。虽然比用纯二进制编码效率低,但由于结构简单而且不受字节存储顺序影响(所有数字以十进制编码,不存在大端小端的问题)——这对于跨平台性非常重要。而且具有较好的灵活性,即使存在故障的字典键,只要将其忽略并更换新的就能兼容补充,更多介绍见维基百科

这种编码方式支持四种类型的数据:string, int, Dictionary<string, object>, List<object>,各自的编码规则如下:

1.1 string类型

string类型的编码格式为[length]:[string]。以字符串的长度开头,加一个冒号,并以字符串内容结束。示例:

"abc" => 3:abc

1.2 int类型

int类型的编码格式为i[int]e。以i开头,加上数字,以e结尾。 示例:

123 => i123e

1.3 List<object>类型

List<object>类型的编码格式为l[object]e。以l开头,加上列表中各个元素的编码(元素的类型同样为BEncoding支持的类型),以e结尾。 示例:

List<"abc", 123> => l3:abci123ee

1.4 Dictionary<string, object>类型

Dictionary<string, object>类型的编码格式为d[Key-Value Pair]e。以d开头,加上字典中每个键值对的编码,以e结尾。示例:

Dictionary<{"name":"create chen"},{"age":23}> => d4:name11:create chen3:agei23ee

感兴趣的朋友可以自己写着玩玩 

2. BEncoding编码

2.1 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public static string Encode(object obj)
{
    var sb = new StringBuilder();
    if(obj is Dictionary<string,object>)
    {
        var parseObj = obj as Dictionary<string, object>;
        sb.Append("d");
        foreach (var o in parseObj)
        {
            sb.AppendFormat("{0}:{1}{2}", o.Key.Length,o.Key, Encode(o.Value));
        }
        sb.Append("e");
    }
    if ((obj as int?) != null)
    {
        var parseObj = (int) obj;
        sb.AppendFormat("i{0}e", parseObj);
    }
    if (obj is List<object>)
    {
        var parseObj = obj as List<object>;
        sb.Append("l");
        foreach (var o in parseObj)
        {
            sb.Append(Encode(o));
        }
        sb.Append("e");
    }
    if (obj is string)
    {
        var parseObj = obj as string;
        sb.AppendFormat("{0}:{1}", parseObj.Length, parseObj);
    }
    return sb.ToString();
}

2.2 测试对象:

1
2
3
4
5
6
7
var obj = new Dictionary<string, Object>
    {
        {"nick", "Create Chen"},
        {"age", 23},
        {"blog","http://www.cnblogs.com/technology"},
        {"hobbies", new List<object> {"Coding", "Basketball"}}
    };

2.3 输出:

d4:nick11:Create Chen3:agei23e4:blog33:http://www.cnblogs.com/technology7:hobbiesl6:Coding10:Basketballee

3. BEncoding解码

3.1 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
public static object Decode(string s)
{
    return DecodeObject(s, ref _index, EncodeState.Value);
}
 
private enum EncodeState
{
    Key,
    Value
}
 
private static int _index;
 
private static object DecodeObject(string str,ref int index, EncodeState state)
{
    var obj = new Dictionary<string, object>();
 
    var c = str[index];
    while (c != 'e')
    {
        if (c == 'd')//字典类型
        {
            index++;
            return DecodeObject(str, ref index,EncodeState.Key);
        }
        if (c == 'i')//数字类型
        {
            var value = "";
            index++; c = str[index];
            while (c != 'e')
            {
                value += c.ToString(CultureInfo.InvariantCulture);
                index++;
                c = str[index];
            }
            return Convert.ToInt32(value);
        }
        if (c == 'l')//列表类型
        {
            index++;
            var value = new List<object>();
            while (str[index]!='e')
            {
                value.Add(DecodeObject(str, ref index, EncodeState.Value));
                index++;
            }
            return value;
        }
        if ('0' < c && c <= '9') //字符串类型
        {
            string strLength = "";
            while (c != ':')
            {
                strLength += c.ToString(CultureInfo.InvariantCulture);
                c = str[++index];
            }
            var length = Convert.ToInt32(strLength);
            var strContent = "";
            for (int i = 0; i < length; i++)
            {
                strContent += str[index + 1].ToString(CultureInfo.InvariantCulture);
                index++;
            }
            if (state == EncodeState.Value)
            {
                return strContent;
            }
            index++;
            obj.Add(strContent, DecodeObject(str, ref index, EncodeState.Value));
            state = EncodeState.Key;
            index++;
        }
        c = str[index];
    }
    return obj;
}

3.2 测试对象:

d4:nick11:Create Chen3:agei23e4:blog33:http://www.cnblogs.com/technology7:hobbiesl6:Coding10:Basketballee

3.3 还原类型

4. 代码下载

本文链接:http://www.cnblogs.com/technology/p/BEncoding.html

BEncoding的编码与解码的更多相关文章

  1. java编码原理,java编码和解码问题

    java的编码方式原理 java的JVM的缺省编码方式由系统的“本地语言环境”设置确定,和操作系统的类型无关 . 在JAVA源文件-->JAVAC-->Class-->Java--& ...

  2. IO(六)--- 编码和解码

    编码: 把看得懂的字符变成看不懂码值这个过程我们称作为编码. 解码: 把码值查找对应的字符,我们把这个过程称作为解码. 注意: 以后编码与解码一般我们都使用统一的码表.否则非常容易出乱码. 常用码表: ...

  3. RapidJSON 代码剖析(三):Unicode 的编码与解码

    根据 RFC-7159: 8.1 Character Encoding JSON text SHALL be encoded in UTF-8, UTF-16, or UTF-32. The defa ...

  4. BASE64编码和解码(VC源代码) 并 内存加载 CImage 图像

      BASE64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本.完整的BASE64定义可见 RFC1421和 RFC2045.编码后的数据比原始数据略长,为原来的4/3.在电子 ...

  5. Android 中的编码与解码

    前言:今天遇到一个问题,一个用户在登录的时候,出现登录失败.但是其他用户登录都是正常的,经过调试发现登录失败的用户的密码中有两个特殊字符: * .#  . 特殊符号在提交表单的时候,出现了编码不一样的 ...

  6. base64编码、解码的C语言实现

    转自:http://www.cnblogs.com/yejianfei/archive/2013/04/06/3002838.html base64是一种基于64个可打印字符来表示二进制数据的表示方法 ...

  7. android Java BASE64编码和解码二:图片的编码和解码

    1.准备工作 (1)在项目中集成 Base64 代码,集成方法见第一篇博文:android Java BASE64编码和解码一:基础 (2)添加 ImgHelper 工具类 package com.a ...

  8. android Java BASE64编码和解码一:基础

    今天在做Android项目的时候遇到一个问题,需求是向服务器上传一张图片,要求把图片转化成图片流放在 json字符串里传输. 类似这样的: {"name":"jike&q ...

  9. Web开发须知:URL编码与解码

    通常如果一样东西需要编码,说明这样东西并不适合传输.原因多种多样,如Size过大,包含隐私数据,对于Url来说,之所以要进行编码,是因为Url中有些字符会引起歧义. 例如,Url参数字符串中使用key ...

随机推荐

  1. 快捷键让SublimeText在编文件快速在浏览器打开

    这里插入一下安装"view in browser"官方版的说明:(前提是得先安装package control插件) 1.通过"ctrl+shift+p"打开命 ...

  2. Meteor入门

    转载Meteor入门介绍   Meteor是什么 基于nodejs的实时web APP开发框架. Meteor能带来什么 简单的说,你可以用js搞定客户端.服务端的开发.另外,客户端.服务端的界限被极 ...

  3. 7.Swift翻译教程系列——控制循环的流程

    英语PDF下载链接http://download.csdn.net/detail/tsingheng/7480427 Swift提供了类C语言类似的控制流结构.包含for循环和while循环来多次运行 ...

  4. Spring该讲座

    看看今天Spring. 国内搞Java开发的朋友们.对Spring一定不会陌生. Spring的历史? 谈起Spring.就会想起Ejb2.0.虽然.现实中有非常多基于Ejb2.0的成功系统,可是Ej ...

  5. ASP.NET MVC性能优化工具 MiniProfiler

    ASP.NET MVC性能优化工具 MiniProfiler 2014年04月19日 ⁄ ASP.NET ⁄ 共 1159字 ⁄ 字号 小 中 大 ⁄ 暂无评论 ⁄ 阅读 325 views 次 MV ...

  6. Equals 和==

    class Person     {         private string name;         public string Name         {             get ...

  7. 创建GitHub技术博客

    创建GitHub技术博客全攻略 githubio技术博客网站生成 说明: 首先,你需要注册一个 github 账号,最好取一个有意义的名字,比如姓名全拼,昵称全拼,如果被占用,可以加上有意义的数字.本 ...

  8. Linux中iptables设置详细

    无论如何,iptables是一个需要特别谨慎设置的东西,万一服务器不在你身边,而你贸然设置导致无法SSH,那就等着被老板骂吧,呵呵... 一下内容是为了防止这种情况发生而写的,当然很初级,不过一般服务 ...

  9. socket在windows下和linux下的区别

    原文:socket在windows下和linux下的区别 1)头文件 windows下winsock.h/winsock2.h linux下sys/socket.h    错误处理:errno.h 2 ...

  10. curl_setopt(): CURLOPT_FOLLOWLOCATION cannot be activated when in safe_mode or an open_basedir is set in

    当系统开启safe_mode和 open_basedir,在程序中使用以下语句 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); 并且遇到301,302状态 ...