读取文件,查找模式,编辑并写回同一二进制文件

时间:2019-06-10 18:04:22

标签: python

我正在尝试读取一个包含多行数据的文件,修改其中一行并将修改内容写回到我读取的同一文件中。

文件位于PC上的特定位置,看起来像这样:

"0000000000 55 4F 50 44 01 00 00 00 00 00 00 00 00 06 05 08 07 AA_BB584982"

这是一行数据,像这样的任意数字以类似的方式重复。我只想将此文件的第一行中的08 07部分清零。任何帮助/想法非常感谢。谢谢!

编辑:输入文件为.bin格式,它们不一定都具有相同的模式,但是要归零的值的位置在各个文件中始终相同。现在,这更像是计数要修改的字节数,而不是模式匹配。

3 个答案:

答案 0 :(得分:2)

使用它根据模式进行修改:

import re
from os import rename

path = r'/path/to/binary'
tmp_file = path + r'.mod'

pattern = b'\x55\x4F\x50\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x06\x05\x08\x07'
new_pat = b'\x55\x4F\x50\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x06\x05\xde\xad'

myre = re.compile(pattern)
with open(path, 'rb') as read_file, open(tmp_file, 'wb') as write_file:
    write_file.write(myre.sub(new_pat, read_file.read()))

rename(tmp_file, path)

使用它根据位置进行修改:

import struct
from collections import defaultdict
from os import rename

path = r'/tmp/rando_bin'
tmp_file = path + r'.mod'

location_start_hex = 0
location_end_hex = 8
fill_value = 0

mapper = defaultdict(set)
for hex_location in range(location_start_hex, location_end_hex + 1):
    mapper[hex_location // 2].add('right' if hex_location % 2 else 'left')


with open(path, 'rb') as read_file, open(tmp_file, 'wb') as write_file:
    byte_cnt = 0
    x = read_file.read(1)

    while x:
        if byte_cnt in mapper:
            if len(mapper[byte_cnt]) == 2:
                write_file.write(bytearray([fill_value]))
            elif 'left' in mapper[byte_cnt]:
                y = struct.unpack('B', x)[0]
                new_byte = y & int('00001111', 2)
                write_file.write(bytearray([new_byte]))
            else:
                y = struct.unpack('B', x)[0]
                new_byte = y & int('11110000', 2)
                write_file.write(bytearray([new_byte]))
        else:
            write_file.write(x)
        byte_cnt += 1
        x = read_file.read(1)

rename(tmp_file, path)

关于按位置脚本进行修改的一些注意事项:

  • 由于python的read()至少只能读取8位元的大小,并且我们需要修改4位元的大小(又称为半字节又称为十六进制数字),因此当我们仅需要修改一半阅读。这就是leftright的含义。他们告诉我们修改8位的左侧部分或8位的右侧部分。
  • leftright可以分别是01,但我这样保留它们是为了使代码更易于理解。
  • location_start_hex0开始,转换为修改第一个十六进制数字。
  • 修改中包括位于location_end_hex的十六进制数字。
  • read(1)一次读取8位。
  • 您无法使用此代码修改任何位块。您只能修改一组4位,它与二进制文件的开头之间的偏移是4的倍数。但这足以解决这个问题。
  • 此处的struct(与C的{​​{1}}密切相关)用于使位被读取为整数,从而允许我们使用bit对其进行操作明智的操作。

答案 1 :(得分:0)

这个怎么样?这可能不是最有效的方法,但应该可以。

file=open("your_file_here", "r")
data=file.read().split("\n")
file.close()
for i in data[0].split(" "):
    if i == "08" or i == "07":
        i = "00"
    else:
        pass
file = open("your_file_here", "w")
for i in data:
    file.write(i+"\n")
file.close()

编辑:我知道我在技术上将新文件写入到旧文件的相同位置,但是它应该与修改文件具有相同的效果,不是吗?

答案 2 :(得分:0)

input_file_path = r'C:\path\to\file.txt'
with open(input_file_path, 'r') as in_file:
    first_line, *rest = in_file.readlines()

first_line.replace('08 07', '00 00')

with open(input_file_path, 'w') as out_file:
    out_file.write('\n'.join((first_line, *rest))

应该工作。