Python:编辑文件中特定的十六进制值

3
我想编辑一个.m4a文件(音频文件)中特定的数据行,但我不知道如何用Python做到。我知道有其他类似的主题,但当我在十六进制编辑器程序(例如HxD)中打开.m4a文件时,它给我不同于从我的Python脚本中获取的十六进制数据。术语让我有些困惑。我需要做的是使用Python读取文件并将其转换为我的十六进制编辑器使用的格式,替换数据,然后再将其转换回来并将其写入文件。我真不知道这是否可能,或者是否有更简单的方法来完成它。我还是Python新手,还在学习中。我只是需要有人指点我正确的方向。这样做的原因与我一直试图更改的文件元数据有关。
我的Python版本:Python 3.7.4
以下是涉及文件的链接:https://drive.google.com/file/d/1m8SpCLSyX265_I00MFT1IyltpTAvxntF/view?usp=sharing 我的代码:
with open(file, 'rb') as f:
    content = f.read().hex()
print(content)

以下是我需要编辑的行(来自我的十六进制编辑器)
00 00 01 80 68 69 33 32

(文本翻译:你好32)

替换为:

00 00 00 00 68 69 33 32

我的文件在十六进制编辑器中的开头如下所示(使用HxD):
00 00 00 00 00 00 00 00 01 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 01 0C 60 6D 64 69 61 00 00 00 20 6D 64 68 64 00 00 00 00 D9 98 96 40 D9 B2 F7 52 00 00 AC 44 00 84 EC 00 00 00 00 00 00 00 00 22 68 64 6C 72 00 00 00 00 00 00 00 00 73 6F 75 6E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 0C 16 6D 69 6E 66 00 00 00 10 73 6D 68 64 00 00 00 00 00 00 00 00 00 00 00 24 64 69 6E 66 00 00 00 1C 64 72 65 66 00 00 00 00 00 00 00 01 00 00 00 0C 75 72 6C 20 00 00 00 01 00 01 0B DA 73 74 62 6C 00 00 80 76 73 74 73 64 00 00 00 00 00 00 00 01 00 00 80 66 6D 70 34 61 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 02 00 10 00 00 00 00 AC 44 00 00 00 00 00 33 65 73 64 73 00 00 00 00 03 80 80 80 22 00 00 00 04 80 80 80 14 40 15 00 18 00 00 04 82 90 00 03 E8 00 05 80 80 80 02 12 10 06 80 80 80 01 02 00 00 00

我的Python脚本返回的十六进制编码开头如下:
d5df0d0ef02daf279fd6b15fae5c6e0bc79bec22095ceeada5e77371afc8ee36f10773b1b2c06b1b1ee4e5cccbf67403b26fd37cc6e3cc9f11019ab604f0071872ec6c092cc20b2a6d4460c55986623b50

如果您提供有关该文件的链接,可能会对我们有所帮助。 - Ross Jacobs
好主意。已添加一个文件链接。 - Riley Bell
1个回答

3

十六进制读取的差异

当我使用十六进制编辑器程序(例如HxD)打开.m4a文件时,它给出的十六进制数据与我从Python脚本获取的数据不同。

使用Python读取

这是我在Python中看到的内容,显示前32个字符:

with open('01 Choir (Remix).m4a', 'rb') as f:
    content = f.read().hex()
print(content[:32])
00000020667479704d34412000000000

使用xxd阅读

再次使用bash,选择前32个字符:

$ xxd -ps 01\ Choir\ \(Remix\).m4a | head -c 32
00000020667479704d34412000000000

这里的xxd -ps获取文件的十六进制字符串,head获取输出的前32个字符。

请注意,它们是相同的十六进制数。

重写Hex

以下是我需要编辑的行(来自我的十六进制编辑器)

0000018068693332

替换为:

0000000068693332

你已经找到了解决方案的一半——只需进行字符串替换并将其重新写入文件即可。请记住,虽然Python的正则表达式库re在这里更强大,但是它并不必要,因为你只需要进行字符串替换。而且字符串替换比使用正则表达式快一个数量级

如果你确实需要使用正则表达式,那么有很多种编辑Hex的方法

# replace_bytes.py
source_str = '0000018068693332'
replace_str = '0000000068693332'

with open('01 Choir (Remix).m4a', 'rb') as f:
    content = f.read().hex()
print(source_str + " in `01 Choir (Remix).m4a`:       ", source_str in content)
content = content.replace(source_str, replace_str)
with open('01 Choir (Remix) edited.m4a', 'wb') as f:
    f.write(bytes.fromhex(content))

with open('01 Choir (Remix) edited.m4a', 'rb') as f:
    new_content = f.read().hex()
print(source_str + " in `01 Choir (Remix) edited.m4a`:", source_str in new_content)

然后运行它:

$ python replace_bytes.py
0000018068693332 in `01 Choir (Remix).m4a`:        True
0000018068693332 in `01 Choir (Remix) edited.m4a`: False

哇,那真的帮了我大忙!它起作用了。非常感谢。由于某种原因,我打印了(content),然后尝试从Python命令中复制整个十六进制字符串,但结果不同。不太确定为什么。非常感激 :) - Riley Bell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接