python-3.x - 解码种子文件时出现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 在读取时解码文本文件,在写入时编码。默认编码取自 locale.getpreferredencoding(False),显然对于您的设置返回“ASCII”。请参阅 open() 函数文档:
在文本模式下,如果未指定编码,则使用的编码取决于平台:调用 locale.getpreferredencoding(False) 以获取当前的语言环境编码。
您应该使用显式编解码器打开文本文件,而不是依赖系统设置:
当前文件=打开(文件,'rb',编码='latin1',错误='忽略')
您在其中设置编码参数以匹配您正在阅读的文件。
Python 3 支持 UTF-8 作为源代码的默认值。
这同样适用于写入可写文本文件;写入的数据将被编码,如果您依赖系统编码,除非您明确设置合适的编解码器,否则您可能会收到 UnicodeEncodingError 异常。编写时使用什么编解码器取决于您正在编写的文本以及您打算之后对文件执行的操作。
您可能想阅读 Unicode HOWTO 中的 Python 3 和 Unicode,它解释了源代码编码和读写 Unicode 数据。
推荐阅读
- python - 在填充列表的 DataFrame 的每一列上应用一个函数
- flutter - 在 ThemeData 中重用自定义颜色
- django - 如何将自定义数据传递给 django 模板?
- angular - RxJS:为什么订阅没有区别
- android - 发布一个使用房间而不暴露房间的库
- python - 如何评估多个值的 lambda 函数?
- java - 处理 http 多部分响应
- html - webkit 关键帧在 Safari 和 iPhone 中不起作用
- windows - Windows cmd.exe/batch:在一行中将计数器加一?
- business-process-management - 如何在 EPICOR ERP 中限制客户发货时的过度发货