加速(简单)文本处理

时间:2014-04-27 22:53:52

标签: python performance text hex

我需要显示两个文件(大小相等)的数据,以便能够直观地比较它们。为此,我创建了一个由四个Text小部件组成的新Tk小部件。第一个窗口小部件包含表示来自第一个文件的字节的字符,第二个窗口小部件包含左窗口小部件中字节的十六进制值,第三个窗口小部件和第四个窗口中的字节值相同(包含第二个文件的数据/十六进制值)。要显示的输入数据是两个字节数组。

要填充Text小部件,我必须处理输入数据(bytearrays),因为

  • 我必须摆脱不可打印的字符以及导致四个小部件中各个行未对齐的一些字符,
  • 我必须用字节的十六进制值填充第二个/第四个小部件,因此我必须将字节值转换为十六进制数。

我使用的代码执行了所描述的功能,它适用于小文件(几百千字节)。但是,当我尝试加载更大的文件(几兆字节)时,处理和加载数据所花费的时间是不可接受的(几十秒)。

我可以在此处看到用于显示数据的窗口小部件示例:

data-display widget

要处理输入数据,我使用以下代码。 _ldata_rdata是包含输入数据的字节数组,ldatardata是要在第一个和第三个文本小部件中加载的字符串,lhexdata和{{ 1}}是具有要在第二个和第四个Text小部件中加载的十六进制值的字符串。 rhexdata是一个整数,用于确定一行中将表示的字节数。 wrap函数替换了导致未对齐或无法在文本小部件中选择的所有字符。

print_chars

...

def print_chars(self, byte):
    if (byte < 0x20 or
        (byte > 0x7E and byte < 0xB1)):
        return 0x07
    else:
        return byte

我认为有一种方法可以加快速度,但无法弄明白。在我实现列表理解之前,我曾经用于数据处理的周期,即使对于非常短的输入也是如此。列表理解在性能上有很大改进,但还不够。感谢您的任何建议。

1 个答案:

答案 0 :(得分:1)

我认为通过使用bytearray.translate和适当的转换表而不是使用自己的转义和转换系统,可以改进前两行。然后,您可以将其转换为bytearray.decode的字符串。你还需要一个额外的步骤来将文本分成几行并重新组合,但我怀疑如果你已经完成翻译工作会更快。

table = bytearray.maketrans(bytes(range(0x20))+bytes(range(0x7f, 0xb1)),
                            b"\x07"*(0x20+0xb1-0x7f))

ldata_string = _ldata.translate(table).decode("latin-1") # pick some 8-bit encoding
ldata = "\n".join(ldata_string[i:i+wrap] for i in range(0, len(ldata), wrap))

您可以使用b16encode模块中的base64函数转换为十六进制,然后使用decodebytes输一个字符串。由于每对十六进制数字之间需要空格,拆分和重新连接会变得更复杂,但我怀疑它仍然比单独编码每个字节更快。

import base64

lhexdata_string = base64.b16encode(_ldata).decode("ascii") # hex will always be ASCII
lhexdata = "\n".join(" ".join(hexdata_string[i+j:i+j+2] for i in range(0, 2*wrap, 2))
                     for j in range(0, len(lhexdata_string), 2*wrap))

请注意,上面的代码假定您使用的是Python 3.如果您使用的是Python 2,则需要更改一些内容(例如解决缺少maketrans而不需要decode)。