Python-Hex编辑文件中的特定位置

时间:2014-10-22 14:29:11

标签: python

我想以十六进制格式在文件中打开大约135个不同的偏移量。感兴趣的部分是游戏中角色皮肤的名称,因此编辑这些并保存它们的简单方法可以节省我的MEGA时间。

这是我最终得到的代码,我能理解的东西。我将文件转换为HEX和TEXT格式:

import binascii
filename = 'Skin1.pack'
with open(filename, 'rb') as f:
    content = f.read()
out = binascii.hexlify(content)

f = open('hex.txt', 'wb')
f.write(out)
f.close()

import binascii
filename = 'hex.txt'
with open(filename, 'rb') as f:
    content = f.read()

asci = binascii.unhexlify(content) 
w = open('printed-hex.txt', 'wb')
w.write(asci)
w.close()

现在我尝试使用此字节替换文件中的一些文本

f = open("printed-hex.txt",'r')
filedata = f.read()
f.close()

newdata = filedata.replace("K n i g h t       ",input)

f = open("printed-hex.txt",'w')
f.write(newdata)
f.close()

但我遇到了这个错误,

Traceback (most recent call last):
  File "C:\Users\Dee\Desktop\ARC to HEX\Edit-Printed-HEX.py", line 3, in <module>
    filedata = f.read()
  File "C:\Python34\lib\encodings\cp1252.py", line 23, in decode
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 2656: character maps to                                 <undefined>

2 个答案:

答案 0 :(得分:2)

对于挑剔,hex没有&#39; line&#39;所以你可能想要考虑如何限制你想要编辑的位置。也许编辑固定数量的字节。

您在控制台中看到的输出是python尝试打印二进制数据。它打印了扩展字符,因为它们具有与字符串中的字符对应的可打印字符。您可以看到某些字符是可打印的,这就是为什么您有7(5.之类的内容。

您需要的是一种将二进制数据表示为十六进制的简单方法,以及一种转换回来的方法。我将把实际编辑器的实现留给你。

import mmap

handle = open('/usr/bin/xxd', 'r')
memorymap = mmap.mmap(handle.fileno(), 0, prot=mmap.PROT_READ)

value_to_hex = dict(enumerate('0123456789ABCDEF'))
hex_to_value = {v: k for (k, v) in value_to_hex.items()}


def expand_byte(byte):
    """ Converts a single byte into 2 4 bit values """
    return [(byte >> s) & 0xF for s in [4, 0]]


def compact_bytes(values):
    """ Converts 2 4 bit values into a single byte """
    return (values[0] << 4) | values[1]


def bin_to_hex(data):
    """ Converts binary data to hex characters """
    return [value_to_hex[v] for b in data for v in expand_byte(b)]


def hex_to_bin(hexadecimal):
    """ Converts hex characters to binary data """
    return [
        compact_bytes([hex_to_value[v] for v in hexadecimal[i:i + 2]])
        for i in range(0, len(hexadecimal), 2)
    ]

test_data = [ord(c) for c in memorymap[0:8]]
hex_data = bin_to_hex(test_data)
final_data = hex_to_bin(hex_data)

print "From '{0}'\nto '{1}'\nto '{2}'".format([chr(c) for c in test_data], hex_data, [chr(c) for c in final_data])

打印:

From '['\x7f', 'E', 'L', 'F', '\x02', '\x01', '\x01', '\x00']'
to '['7', 'F', '4', '5', '4', 'C', '4', '6', '0', '2', '0', '1', '0', '1', '0', '0']'
to '['\x7f', 'E', 'L', 'F', '\x02', '\x01', '\x01', '\x00']'

按位值操作是您之前可能没有遇到过的,所以您应该了解它。 >> << |&运算符为bitwise operators

答案 1 :(得分:1)

要检索数据,请像示例代码中那样操作mmap对象;

如果要在十六进制编辑器中打开数据片段,请将其复制到temporary file,然后在编辑器中打开文件,例如使用subprocess.check_call(),然后复制新文件的内容。 (除非您的编辑器有一个命令行选项,允许在启动时将焦点设置为特定的偏移量)

要使用Python的控制台,请使用类似

的内容
" ".join("%02x"%ord(c) for c in <data>)

以十六进制格式查看数据(或只用repr查看以ASCII格式显示),或者,对于更多xxd - 看起来像感觉一样的第三方,如hexview