【问题标题】:Python-Hex editing specific locations in a filePython-Hex 编辑文件中的特定位置
【发布时间】:2014-10-22 14:29:11
【问题描述】:

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

这是我最终得到的代码,我可以理解。我将文件转换为 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>

【问题讨论】:

  • 1) 你坚持在外部编辑器中打开片段还是像代码中显示的那样从 python 的控制台进行编辑可以吗? 2)你如何找到感兴趣的片段?即,这可以自动化吗?
  • 1) 我对使用 python 进行 HEX 编辑一无所知。 2)我不坚持以任何方式打开任何东西,我只是想弄清楚如何做我所说的。
  • “所以,我们的想法是在文件中以十六进制形式打开大约 45 个不同的位置。对于每个选择,我想在十六进制编辑器中编辑 1 到 3 行之间的任何位置。(女巫我假设是我所指的行的片段)“
  • 投反对票可能是因为你问了一个关于用一种语言编程的问题,甚至没有费心去学习它的基础知识。本站不是教程合集,是问答。
  • 我不在乎你的侮辱@chthonicdaemon,我得到了我需要的帮助。他非常乐意帮助我理解我想问的问题。

标签: python


【解决方案1】:

为了挑剔,十六进制没有“线条”,因此您可能需要考虑如何限制要编辑的位置。也许编辑固定数量的字节。

您在控制台中看到的输出是 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']'

按位值操作是您以前可能没有遇到过的,因此您应该了解它。 &gt;&gt; &lt;&lt; |&amp; 运算符是 bitwise operators

【讨论】:

  • 所以这个例子对我来说有点过头了,所有不同的语法,所以我最终尝试了这个。
  • 所以我发布了我最终使用的代码,你有什么可以告诉我为什么我可能会收到这个错误吗?我会使用您提到的方法,但无法使其正常工作。我对 python 和一般编码很陌生。
  • 当我运行您的代码时,它会显示 Traceback(最近一次调用最后一次):文件“C:\Users\Dee\Desktop\ARC to HEX\.PCK to HEX.py”,第 3 行,在 handle = open('/usr/bin/xxd', 'r') FileNotFoundError: [Errno 2] No such file or directory: '/usr/bin/xxd' >>>
  • 我真的不明白您为什么要像这样将这些十六进制值压缩在一起,所以我认为您正在尝试执行字符编码转换。既然您已经解释了问题,我可以提供更多帮助:) 基本上是的,如果您有字符串化的十六进制,您可以通过这种方式将其转换回二进制。请记住,当您拥有像 \x00 这样的序列时,您拥有的是 binary 数据而不是 hex 数据。如果你再次将 binary 数据转换为 binary 你会遇到问题。
  • 正确处理这个主题可能值得另一个问题,而不是一连串的 cmets!
【解决方案2】:

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

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

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

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

以十六进制形式查看数据(或仅以repr 以 ASCII 形式查看数据),或者,为了更多 xxd 的外观和感觉,类似于 hexview 的第 3 方。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多