如何忽略python的“FF FF FF FF”

时间:2013-01-29 01:27:48

标签: python

我有一个大约60 kb的文件,我只想提取数据。该文件中有很多“FF FF FF FF”,我试图提取一切,但“FF FF FF FF”就是一个例子:

46 0D 89 2E 16 FC 1E E6 10 C1 6D 4E 1B 74 5F 1F 
81 07 E2 E7 17 14 77 D4 EA AC BC 20 EA 98 27 FF 
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF

这是我用来获取它的代码:

infile = open("file.bin", "rb") 
    new_pos = int("0xFC0000", 16)
    infile.seek(new_pos, 0)
    chunk = int("0x40000", 16)
    data = infile.read(chunk)
    with open("processed_file.bin", "wb") as outfile:
        outfile.write(data)

它将读取文件并将其保存为“processed file.bin”,但它中包含所有这些“FF FF”。有FF的实例,我需要它找到“FF FF FF FF”并将其从文件中删除,然后将其保存为已处理的文件.bin

任何意见都会受到赞赏。

编辑:为了进一步解释我的意思,这个十六进制在其末尾有FF,

81 07 E2 E7 17 14 77 D4 EA AC BC 20 EA 98 27 FF

我需要将FF保留在最后,但删除FF FF或FF FF FF FF的任何实例。

1 个答案:

答案 0 :(得分:0)

首先,删除每个FF FF显然需要删除每个FF FF FF FF,因此您无需担心该部分。

如果您只想删除对齐的FF FF,那么显而易见的事情就是将其分组为2字节的块。例如,使用标准库itertools recipes中的grouper

data = infile.read(chunk)
data_words = grouper(2, data)
data_words_minus_ffff = (word for word in data_words if word != ('\xFF', '\xFF'))
out_data = flatten(data_words_minus_ffff)
with open("processed_file.bin", "wb") as outfile:
    outfile.write(''.join(out_data))

显然你可以更紧凑地写出来;我这样做是为了清晰起见(所以你可以尝试在每一步打印list(…)以帮助理解它,以防它不明显。)

但是,如果你不关心对齐,你甚至想要删除FF的奇数运行,只要它们长于1?好吧,那么你想将它分组为运行,并丢弃任何超过1的运行。你也可以用itertools执行此操作:

data = infile.read(chunk)
groups = itertools.groupby(data, key=lambda x: x != '\xff')
groups_listified = ((key, list(group)) for key, group in groups)
groups_without_ff_runs = (group for key, group in groups_listified if key or len(group) > 1)
out_data = flatten(groups_without_ff_runs)
with open("processed_file.bin", "wb") as outfile:
    outfile.write(''.join(out_data))

这个有点难以解释,但我再次把它写成一系列单独的步骤,所以你可以在每个步骤后print list(…)看看它在做什么。

if key or len(group) > 1位表示它是非FF字节的运行,或者是超过1个字节的运行。因此,如果您想将此更改为仅保留2字节的FF运行而不是更长的运行,则可以将len(group) > 1更改为len(group) == 2。如果您想保持偶数长度运行,请使用len(group) % 2 == 0。等等。您可以描述的任何条件,都可以放在那里。

或者,为了多样化,让我们明确地做:

data = infile.read(chunk)
run = 0
out_data = []
for byte in data:
    if byte == '\xFF':
        run += 1
    else:
        if run != 1:
            out_data.append('\xFF' * run)
        run = 0
        out_data.append(byte)
with open("processed_file.bin", "wb") as outfile:
    outfile.write(''.join(out_data))

同样,我们保持FF的所有长度超过1个字节的运行。如果您希望保留所有正好为2个字节的运行,只需将run != 1更改为run == 2即可。等等。