Pythonic方式进行十六进制转储文件

8
我的问题很简单:
有没有办法用Python的方式编写这个Bash命令?
hexdump -e '2/1 "%02x"' file.dat

显然,不使用os、popen或任何快捷方式;)
编辑:虽然我没有明确指定,但如果代码在Python3.x中可用,则会很棒。
谢谢!

2/1 "%02x" 是什么意思? - anatoly techtonik
"%02x" 将每个字节打印为两个字符的大写十六进制数,前缀为0。 - peluzza
那么 2/1 呢?对于那些了解 Python,但不熟悉 hexfump cli 的人来说,这个问题会更清晰明了。 - anatoly techtonik
看一下这个链接:<< http://256.com/gray/docs/misc/hexdump_manual_how_to.html >>“迭代计数器默认为1,如果没有提供,则必须提供字节计数。这告诉我们在打印结束字符串之前要进行多少次转换。因此,如果您要解码4个1字节的内容,您需要输入4/1。” - peluzza
3个回答

16

14

如果你只关心Python 2.x,line.encode('hex')会将一段二进制数据编码成十六进制。因此:

with open('file.dat', 'rb') as f:
    for chunk in iter(lambda: f.read(32), b''):
        print chunk.encode('hex')

(如果我没记错,默认情况下,hexdump 每行打印32对十六进制数字; 如果不是,请将该 32 更改为 16 或任何其他数字…)

如果两个参数的iter函数看起来让人困惑,请点击帮助链接;一旦掌握了核心思想,它就不会太复杂。

如果你关注Python 3.x,encode 只适用于将Unicode字符串转换为字节的编解码器; 对于转换另一方向(或任何其他组合)的编解码器,则必须明确使用 codecs.encode

with open('file.dat', 'rb') as f:
    for chunk in iter(lambda: f.read(32), b''):
        print(codecs.encode(chunk, 'hex'))

或者使用hexlify可能更好:

with open('file.dat', 'rb') as f:
    for chunk in iter(lambda: f.read(32), b''):
        print(binascii.hexlify(chunk))

如果您想在打印文件之外进行其他操作,而不是将整个文件读入内存,则可能需要创建迭代器。您可以将此放入函数中并将该print更改为yield,这样该函数将完全返回所需的迭代器。或使用genexpr或map调用:

with open('file.dat', 'rb') as f:
    chunks = iter(lambda: f.read(32), b'')
    hexlines = map(binascii.hexlify, chunks)

没有任何答案涉及如何实现第二部分,即-e '2/1 "%02x。 - Julian

5

只需 read() 整个文件并 encode('hex') 即可。这还有什么比 Python 更 Pythonic 的呢?

with open('file.dat', 'rb') as f:
    hex_content = f.read().encode('hex')

除非你几乎肯定要以rb模式打开它,这样它就不会转换换行符。此外,这是特定于Python 2的;在Python 3中,你不能对字节进行编码。仍然+1。 - abarnert
2
很好的方法,它有效,但只在Python2中可用。这是Py3.4的输出: UnicodeDecodeError: 'utf-8'编解码器无法解码位置0处的字节0xac:无效的起始字节 - peluzza
1
@peluzza:你需要Python 3吗? - abarnert
我正在尽力只编写适用于3.X版本的代码,但是这些空隙太深了,不仅仅是在十六进制转储方面工作 ;) - peluzza
@peluzza:如果你需要更多细节,请参考Raymond Hettinger的回答或者我的回答。 - abarnert

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