我正在翻阅一些包含文本的旧二进制文件.由于某些原因,他们的文本经常使用自定义字符编码,我希望能够阅读和重写它们.
在我看来,实现这一点的适当方法是使用standard codecs library创建自定义编解码器.不幸的是,它的文档既庞大又完全没有实例.谷歌出现了一些,但只针对python2,而我使用的是3.
我正在寻找一个如何使用编解码器库实现自定义字符编码的简单示例.
我正在翻阅一些包含文本的旧二进制文件.由于某些原因,他们的文本经常使用自定义字符编码,我希望能够阅读和重写它们.
在我看来,实现这一点的适当方法是使用standard codecs library创建自定义编解码器.不幸的是,它的文档既庞大又完全没有实例.谷歌出现了一些,但只针对python2,而我使用的是3.
我正在寻找一个如何使用编解码器库实现自定义字符编码的简单示例.
你要的是最低限度的!
CodecInfo
个对象.CodecInfo
对象的函数.下面是一个按顺序将小写字母a-z转换为0-25的示例.
import codecs
import string
from typing import Tuple
# prepare map from numbers to letters
_encode_table = {str(number): bytes(letter, 'ascii') for number, letter in enumerate(string.ascii_lowercase)}
# prepare inverse map
_decode_table = {ord(v): k for k, v in _encode_table.items()}
def custom_encode(text: str) -> Tuple[bytes, int]:
# example encoder that converts ints to letters
# see https://docs.python.org/3/library/codecs.html#codecs.Codec.encode
return b''.join(_encode_table[x] for x in text), len(text)
def custom_decode(binary: bytes) -> Tuple[str, int]:
# example decoder that converts letters to ints
# see https://docs.python.org/3/library/codecs.html#codecs.Codec.decode
return ''.join(_decode_table[x] for x in binary), len(binary)
def custom_search_function(encoding_name):
return codecs.CodecInfo(custom_encode, custom_decode, name='Reasons')
def main():
# register your custom codec
# note that CodecInfo.name is used later
codecs.register(custom_search_function)
binary = b'abcdefg'
# decode letters to numbers
text = codecs.decode(binary, encoding='Reasons')
print(text)
# encode numbers to letters
binary2 = codecs.encode(text, encoding='Reasons')
print(binary2)
# encode(decode(...)) should be an identity function
assert binary == binary2
if __name__ == '__main__':
main()
运行这个 fingerprint
$ python codec_example.py
0123456
b'abcdefg'
有关Codec
界面的详细信息,请参见https://docs.python.org/3/library/codecs.html#codec-objects.尤其是解码功能
... 解码对象input并返回元组(输出对象,长度
而编码功能
... 对对象input进行编码并返回一个元组(输出对象,消耗的长度).
请注意,您还应该担心处理流、增量编码/解码以及错误处理.有关更完整的示例,请参阅@krs013提到的hexlify codec.
另外,你也可以用codec.open(..., encoding='Reasons')
代替codec.decode
.