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
Bencode的编码与解码的更多相关文章
- java编码原理,java编码和解码问题
java的编码方式原理 java的JVM的缺省编码方式由系统的“本地语言环境”设置确定,和操作系统的类型无关 . 在JAVA源文件-->JAVAC-->Class-->Java--& ...
- IO(六)--- 编码和解码
编码: 把看得懂的字符变成看不懂码值这个过程我们称作为编码. 解码: 把码值查找对应的字符,我们把这个过程称作为解码. 注意: 以后编码与解码一般我们都使用统一的码表.否则非常容易出乱码. 常用码表: ...
- RapidJSON 代码剖析(三):Unicode 的编码与解码
根据 RFC-7159: 8.1 Character Encoding JSON text SHALL be encoded in UTF-8, UTF-16, or UTF-32. The defa ...
- BASE64编码和解码(VC源代码) 并 内存加载 CImage 图像
BASE64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本.完整的BASE64定义可见 RFC1421和 RFC2045.编码后的数据比原始数据略长,为原来的4/3.在电子 ...
- Android 中的编码与解码
前言:今天遇到一个问题,一个用户在登录的时候,出现登录失败.但是其他用户登录都是正常的,经过调试发现登录失败的用户的密码中有两个特殊字符: * .# . 特殊符号在提交表单的时候,出现了编码不一样的 ...
- base64编码、解码的C语言实现
转自:http://www.cnblogs.com/yejianfei/archive/2013/04/06/3002838.html base64是一种基于64个可打印字符来表示二进制数据的表示方法 ...
- android Java BASE64编码和解码二:图片的编码和解码
1.准备工作 (1)在项目中集成 Base64 代码,集成方法见第一篇博文:android Java BASE64编码和解码一:基础 (2)添加 ImgHelper 工具类 package com.a ...
- android Java BASE64编码和解码一:基础
今天在做Android项目的时候遇到一个问题,需求是向服务器上传一张图片,要求把图片转化成图片流放在 json字符串里传输. 类似这样的: {"name":"jike&q ...
- Web开发须知:URL编码与解码
通常如果一样东西需要编码,说明这样东西并不适合传输.原因多种多样,如Size过大,包含隐私数据,对于Url来说,之所以要进行编码,是因为Url中有些字符会引起歧义. 例如,Url参数字符串中使用key ...
随机推荐
- 【jquery】:表单返回信息
第一个页面 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...
- js 图片预览
图片预览 $('#pac_recipe').change(function() { var imgsrc = ''; ]) { //chrome firefox imgsrc = window.URL ...
- 关于CSS3的代码总结(部分)
1. 构造样式表:selector{ Property:value; Property:value; } Selector是需要更改样式的元素,property为css属性的名称,value应用的哪种 ...
- MySQL Connector/J 6.x jdbc.properties 配置, mysql-connector-java-6.0.4.jar 异常
今天学习SSM框架整合,完成Spring和mybatis这两大框架的整合做测试时候出来很多问题,主要来自于配置文件. 我这里重点说一下Mysql数据驱动配置. 配置pom.xml时候去网站 MySQL ...
- 条形码软件开发包Dynamic .NET TWAIN v5.0提供WPF功能
Dynamsoft是一家著名的开发条形码控件开发包的公司,其旗下 Dynamic .NET TWAIN产品近日升级到v5.0版本,对于在支持WPF功能方面有着较大的改进.下面就让我们一起来看看这次更新 ...
- hibernate连接查询
Hibernate的HQL语言类似于SQL语言,更适合于Java面向对象的思想. 类与数据库映射好了,不必考虑数据库. 实现Class1的表与Class2的表的联合查询: Class1的class2属 ...
- Eclipse进行C/C++开发——Eclipse+CDT+MinGW的配置与使用详解
http://hi.baidu.com/ltb6w/item/3a51f11926fda60ce75c361d Eclipse进行C/C++开发——Eclipse+CDT+MinGW的配置与使用详解 ...
- WP8:在Cocos2d-x中使用OpenXLive
一. Cocos2d-x for Windows Phone 到2013年底,几大手游引擎都陆续支持WP8了,特别是Unity3D和Cocos2d-x.有过游戏开发经验的朋友们应该对这两个引擎不 ...
- 跟我一起学WCF(11)——WCF中队列服务详解
一.引言 在前面的WCF服务中,它都要求服务与客户端两端都必须启动并且运行,从而实现彼此间的交互.然而,还有相当多的情况希望一个面向服务的应用中拥有离线交互的能力.WCF通过服务队列的方法来支持客户端 ...
- 聊聊JS与设计模式之(工厂Factory)篇------(麦当劳的故事)
一,总体概要 1,笔者浅谈 说起设计模式其实并不是什么很新奇的概念,它也不是基于特定语言所形成的产物,它是基于软件设计原则以及相关的方法论和经过特定时期衍生出的若干解决方案.本文会以一个实例带入大家学 ...