Bencode的编码与解码

开源地址: https://github.com/CreateChen/Bencode

Nuget: Install-Package Bencode

1. Bencode规则

        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. Bencode编码

2.1 代码:

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 测试对象:

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 代码:

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

posted @ 2013-10-01 13:07  Create Chen  阅读(...)  评论(...编辑  收藏