近期搞项目中遇到Bencode解码的问题,就用Py写了个Bencode解码的代码。作为笔记保存参考。

BEncoding是BitTorrent用在传输数据结构的编码方式,这种编码方式支持四种类型的数据:string, int, Dictionary<string, object>, List<object>,各自的编码规则如下:

    • string类型的编码格式为[length]:[string]。以字符串的长度开头,加一个冒号,并以字符串内容结束。示例:"abc" => 3:abc
    • int类型的编码格式为i[int]e。以i开头,加上数字,以e结尾。 示例:123 => i123e
    • List<object>类型的编码格式为l[object]e。以l开头,加上列表中各个元素的编码(元素的类型同样为BEncoding支持的类型),以e结尾。 示例:List<"abc", 123> => l3:abci123ee
    • Dictionary<string, object>类型的编码格式为d[Key-Value Pair]e。以d开头,加上字典中每个键值对的编码,以e结尾。
# 解析List<object>类型,例:l3:abci123ee => List<"abc", 123>
def decode_list(str,p):
    l = len(str)
    # print(l)
    # print(p)
    list = []
    while p < l:
        if str[p + 1].isdigit():
            f_m = str.index(":",p + 1,l)
            f_n = int(str[p + 1:f_m])
            f_e = f_m + f_n
            data_str = str[f_m + 1:f_e + 1]
            list.append(data_str)
            p = f_e
        elif str[p + 1] == "i":
            end = str.index("e", p + 1, l)
            data_int = str[p + 2: int(end)]
            list.append(data_int)
            p = end
        elif str[p + 1] == "e":
            p = p + 2
            list.append("p")
            list.append(p)
            break
        elif str[p + 1] == "l":
            p = p + 1
    return list
 
# 解析Dictionary<string, object>类型,例:d4:name11:create chen3:agei23ee => Dictionary<{"name":"create chen"},{"age":23}>
def decode_dict(str,p):
    test = decode_list(str,p)
 
    data_seq = []
    data_val = []
 
    i = 0
    while i < len(test):
        data_seq.append(test[i])
        data_val.append(test[i + 1])
        i = i + 2
 
    data_dict = dict.fromkeys(data_seq)
 
    i = 0
    while i < len(test) / 2:
        data_dict[data_seq[i]] = data_val[i]
        i = i + 1
 
    return data_dict
 
data = "d4:name11:create chen3:agei23eel3:abci123eei23e3:age"
print(data)
# 定义全局指针,追踪所查位置
global p
l = len(data)
p = 0
while p < l:
    # 判断是否为dict型
    if data[p] == "d":
        data_dict = decode_dict(data,p)
        p = int(data_dict["p"])
        del data_dict["p"]
        print(data_dict)
        f = open("text.txt","a+")
        for k, v in data_dict.items():
            f.write(k + ":" + str(v))
            f.write("\n")
        f.close()
    # 判断是否为list型
    elif data[p] == "l":
        data_list = decode_list(data,p)
        p = int(data_list[-1])
        del data_list[-1]
        del data_list[-1]
        print(data_list)
        f = open("text.txt", "a+")
        for i in data_list:
            f.write(i)
            f.write("\n")
        f.close()
    # 判断是否为str型,解析
    elif data[p] == "i":
        f = data.index("e",p,l)
        data_int = data[p + 1:f]
        p = f + 1
        print(data_int)
        f = open("text.txt", "a+")
        f.write(data_int)
        f.write("\n")
        f.close()
    # 判断是否为int型,解析(为了方便,暂未将其结果转为int型,而是str型,例:“123”
    elif data[p].isdigit():
        f = data.index(":",p,l)
        print(data[f])
        data_str = data[f + 1:int(data[p:f]) + f + 1]
        print(data_str)
        p = int(data[p:f]) + f + 1
        f = open("text.txt", "a+")
        f.write(data_str)
        f.write("\n")
        f.close()
print("It's done")

  

python实现Bencode解码方法的更多相关文章

  1. python字符串操作实方法大合集

    python字符串操作实方法大合集,包括了几乎所有常用的python字符串操作,如字符串的替换.删除.截取.复制.连接.比较.查找.分割等,需要的朋友可以参考下:   #1.去空格及特殊符号 s.st ...

  2. [LeetCode] 639. Decode Ways II 解码方法 II

    A message containing letters from A-Z is being encoded to numbers using the following mapping way: ' ...

  3. [LeetCode] Decode Ways 解码方法

    A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...

  4. python 类属性与方法

    Python 类属性与方法 标签(空格分隔): Python Python的访问限制 Python支持面向对象,其对属性的权限控制通过属性名来实现,如果一个属性有双下划线开头(__),该属性就无法被外 ...

  5. Python执行系统命令的方法 os.system(),os.popen(),commands

    os.popen():用python执行shell的命令,并且返回了结果,括号中是写shell命令 Python执行系统命令的方法: https://my.oschina.net/renwofei42 ...

  6. python 调用 shell 命令方法

    python调用shell命令方法 1.os.system(cmd) 缺点:不能获取返回值 2.os.popen(cmd) 要得到命令的输出内容,只需再调用下read()或readlines()等   ...

  7. python 面向对象、特殊方法与多范式、对象的属性及与其他语言的差异

    1.python 面向对象 文章内容摘自:http://www.cnblogs.com/vamei/archive/2012/06/02/2532018.html   1.__init__() 创建对 ...

  8. python 字典内置方法get应用

    python字典内置方法get应用,如果我们需要获取字典值的话,我们有两种方法,一个是通过dict['key'],另外一个就是dict.get()方法. 今天给大家分享的就是字典的get()方法. 这 ...

  9. [转] python程序的调试方法

    qi09 原文 python程序的调试方法 本文讨论在没有方便的IDE工具可用的情况下,使用pdb调试python程序 源码例子 例如,有模拟税收计算的程序: #!/usr/bin/python de ...

随机推荐

  1. POJ 1458 Common Subsequence(最长公共子序列)

    题目链接Time Limit: 1000MS Memory Limit: 10000K Total Submissions: Accepted: Description A subsequence o ...

  2. ArcGIS JS 之通过代理配置ArcGIS Server服务 token

    ArcGIS JS 代理 1.ArcGIS Server Manager中配置访问服务的用户名.密码.角色等,并配置地图服务的具体角色名称 2.在ArcGIS JS中配置使用代理,下述代码将esri的 ...

  3. Arm-Linux 移植 Nginx

    有关博客: <Windows 编译安装 nginx 服务器 + rtmp 模块>.<Ubuntu 编译安装 nginx>.<Arm-Linux 移植 Nginx> ...

  4. Delphi调用爷爷类的方法(自己构建一个procedure of Object)

    Delphi通过inherited 可以调用父类的方法,但是没有提供直接调用父类的父类的方法(爷爷类),通过变通的方式实现如下: 假设父类是TFather,爷爷类TGrand,调用爷爷类的Write方 ...

  5. Spring Boot异步发送邮件和请求拦截器配置

    用户登录流程图: 在spring拦截器中进行鉴权操作: 控制器的拦截: import com.mooc.house.common.model.User; import org.springframew ...

  6. lucene中Field简析

    http://blog.csdn.net/zhaoxiao2008/article/details/14180019 先看一段lucene3代码 Document doc = new Document ...

  7. string.join用法

    C# String.Join用法 String.Join(String, String[]) 在指定 String 数组的每个元素之间串联指定的分隔符 String,从而产生单个串联的字符串 例如: ...

  8. jquery easyui datagrid 在翻页以后仍能记录被选中的行及刷新设置选中行数据

    //easyUI的datagrid在复选框多选时,如何在翻页以后仍能记录被选中的行://注意datagrid中需要配置idField属性,一般为数据的主键 $.ajax({ type: 'GET', ...

  9. Thread-specific data(TSD)线程私有数据

    Thread-specific data(TSD)线程私有数据 http://blog.chinaunix.net/uid-26885237-id-3209913.html linux多线程编程中引入 ...

  10. mysql 数据库 规范

    目录 mysql 数据库 规范 基础规范 命名规范 表设计规范 字段设计规范 索引设计规范 SQL编写规范 行为规范 mysql 数据库 规范 基础规范 必须使用InnoDB存储引擎 解读:支持事务. ...