首页 > 解决方案 > 解码种子文件时出现UnicodeDecodeError

问题描述

我试图从头开始编写 torrent 应用程序只是为了学习目的。所以在阅读 wiki 几个小时后,我编写了一些用于解码使用“Bencoding”的 torrent 文件的代码“ https://en.wikipedia.org/wiki/本码”。但不幸的是,我没有注意到字节字符串和 python 字符串。我的代码适用于像 torrent 数据这样的 python 字符串,但是当我传递 torrent 字节数据时,我得到了编码错误。

我试过“ open(file, 'rb',encoding='utf-8', errors='ignore') ”。它确实将字节字符串更改为 python 字符串。我还在 stakoverflow 上尝试了所有可用的答案。但是一些数据作为错误丢失了,所以我无法正确解码 torrent 数据。请原谅我乱七八糟的编码,请帮助......我还阅读了 bencoder 库,它直接在字节字符串上工作,所以如果有任何方法我不必重新编写代码,请......

with open(torrent_file1, 'rb') as _file:
    data = _file.read()

def int_decode(meta, cur):
    print('inside int_decode function')
    cursor = cur
    start = cursor + '1'
    end = start
    while meta[end] != 'e':
        end += 1
    value = int(meta[start:end])
    cursor = end + 1
    print(value, cursor)
    return value, cursor


def chr_decode(meta, cur):
    print('inside chr_decode function')
    cursor = cur
    start = cursor
    end = start
    while meta[end] != ':':
        end += 1
    chr_len = int(meta[start:end])
    chr_start = end + 1
    chr_end = chr_start + chr_len
    value = meta[chr_start:chr_end]
    cursor = chr_end
    print(value, cursor)
    return value, cursor

def list_decode(meta, cur):
    print('inside the list decoding')
    cursor = cur+1
    new_list = list()
    while cursor < (len(meta)):
        if meta[cursor] == 'i':
            item, cursor = int_decode(meta, cursor)
            new_list.append(item)

        elif meta[cursor].isdigit():
            item, cursor = chr_decode(meta, cursor)
            new_list.append(item)

        elif meta[cursor] == 'e':
            print('list is ended')
            cursor += 1
            break

    return (new_list,cursor)

def dict_decode(meta, cur=0, key_=False, key_val=None):
    if meta[cur] == 'd':
        print('dict found')
    new_dict = dict()
    key = key_
    key_value = key_val
    cursor = cur + 1
    while cursor < (len(meta)):

        if meta[cursor] == 'i':
            value, cursor = int_decode(meta, cursor)
            if not key:
                key = True
                key_value = value
            else:
                new_dict[key_value] = value
                key = False

        elif meta[cursor].isdigit():
            value, cursor = chr_decode(meta, cursor)
            if not key:
                key = True
                key_value = value
            else:
                new_dict[key_value] = value
                key = False
        elif meta[cursor] == 'l':
            lists, cursor = list_decode(meta, cursor)             
            if key:
                new_dict[key_value] = lists
                key = False
            else:
                print('list cannot be used as key')


        elif meta[cursor] == 'd':
            dicts, cursor = dict_decode(meta, cursor)
            if not key:
                key=True
                key_value = dicts
            else:
                new_dict[key_value] = dicts
                key=False

        elif meta[cursor] == 'e':
            print('dict is ended')
            cursor += 1
            break


    return (new_dict,cursor)

test = 'di323e4:spami23e4:spam5:helloi23e4:spami232ei232eli32e4:doneei23eli1ei2ei3e4:harmee'
test2 = 'di12eli23ei2ei22e5:helloei12eli1ei2ei3eee'
test3 = 'di12eli23ei2ei22ee4:johndi12e3:dggee'
print(len(test2))
new_dict = dict_decode(data)
print(new_dict)

回溯(最后一次调用):文件“C:\Users\yewaiyanoo\Desktop\python\torrent\read_torrent.py”,第 8 行,数据 = _file.read() 文件“C:\Users\yewaiyanoo\AppData\ Local\Programs\Python\Python37-32\lib\codecs.py”,第 701 行,在读取返回 self.reader.read(size) 文件“C:\Users\yewaiyanoo\AppData\Local\Programs\Python\Python37- 32\lib\codecs.py",第 504 行,读取 newchars,decodedbytes = self.decode(data, self.errors) UnicodeDecodeError: 'utf-8' codec can't decode byte 0xad in position 204: invalid start byte

标签: python-3.x

解决方案


Python 3 在读取时解码文本文件,在写入时编码。默认编码取自 locale.getpreferredencoding(False),显然对于您的设置返回“ASCII”。请参阅 open() 函数文档:

在文本模式下,如果未指定编码,则使用的编码取决于平台:调用 locale.getpreferredencoding(False) 以获取当前的语言环境编码。

您应该使用显式编解码器打开文本文件,而不是依赖系统设置:

当前文件=打开(文件,'rb',编码='latin1',错误='忽略')

您在其中设置编码参数以匹配您正在阅读的文件。

Python 3 支持 UTF-8 作为源代码的默认值。

这同样适用于写入可写文本文件;写入的数据将被编码,如果您依赖系统编码,除非您明确设置合适的编解码器,否则您可能会收到 UnicodeEncodingError 异常。编写时使用什么编解码器取决于您正在编写的文本以及您打算之后对文件执行的操作。

您可能想阅读 Unicode HOWTO 中的 Python 3 和 Unicode,它解释了源代码编码和读写 Unicode 数据。


推荐阅读