0

我正在尝试比较一些字节值 - 源 A 来自正在“读取”的文件:

f = open(fname, "rb")
f_data = f.read()
f.close()

这些文件的大小可以从几 Kb 到几 Mb 不等

源 B 是已知模式的字典:

eof_markers = {
    'jpg':b'\xff\xd9',
    'pdf':b'\x25\x25\x45\x4f\x46',
    }

(一旦基本流程有效,此列表将被扩展)

本质上,我正在尝试“读取”文件(源 A),然后逐步检查最后一个字节是否与模式列表testString = f_data[-counter:]匹配.

我已经尝试了多种不同的方法来使其正常工作,我可以让 testString 正确递增,但我一直遇到编码问题,各种方法都希望对字节进行 ASCII 化以进行比较。

我有点迷茫,并不是第一次在代码中徘徊,更改intub也没有遇到像d9保留值这样的问题,因此无法使用 ASCII 类型比较工具,例如if format_type in testString:(导致UnicodeDecodeError: 'ascii' codec can't decode byte a9

我试图将所有内容都转换为整数,但这引发了这个错误:ValueError: invalid literal for int() with base 2: '.'或者ValueError: invalid literal for int() with base 10: '.'我试图将其转换testString为十六进制字节,但不断得到TypeError: hex() argument can't be converted to hex(这比我确定的其他任何事情都更缺乏理解!....)

我发现有很多资源可以讨论编码/十六进制比较,例如 stackoverflow.com/questions/10561923/unicodedecodeerror-ascii-codec-cant-decode-byte-0xef-in-position-1),我已经只是没有找到我可以完全理解的东西,或者指出我走上正确道路的东西。

我一直坚持这一点已经有一段时间了,所以任何指点都非常感激。

4

2 回答 2

1

我不确定你到底想要做什么,但我在 Python 3.2.3 中运行了这段代码。

#f = open(fname, "rb")
#f_data = f.read()
#f.close()
f_data = b'\x12\x43\xff\xd9\x00\x23'
eof_markers = {
    'jpg':b'\xff\xd9',
    'pdf':b'\x25\x25\x45\x4f\x46',
    }

for counter in range(-4, 0):
  for name, marker in eof_markers.items():
    print(counter, ('' if marker in f_data[counter:] else '!') + name)

我使用的是硬编码的 f_data,但您可以通过取消注释第 1-3 行和注释第 4 行来撤消它。

这是输出:

-4 !pdf
-4 jpg
-3 !pdf
-3 !jpg
-2 !pdf
-2 !jpg
-1 !pdf
-1 !jpg

有没有你需要做的没有做的事情?

于 2012-09-25T00:24:16.027 回答
0

我不知道如何评论您的主要帖子而不是制作子帖子。无论如何,我有你的一些问题的答案..

  • int(v) 将格式化的数字(例如'599')转换为整数,而不是将字符(例如“!”)转换为其整数值。你会想要 ord() 。但是,我认为没有理由在这种情况下需要使用任何一种。

  • 十六进制!=二进制。十六进制只是一个数字基数。二进制是原始字节值,可能无法打印,具体取决于它们的值。这就是为什么它们显示为“\xfd”之类的转义码。这就是 Python 向您表示不可打印字符的方式——作为十六进制代码。但是它们仍然是没有特殊状态的单个字符——它们不需要转换。将 'A' 与 '\xfd' 进行比较是完全有效的。因此,您应该能够在没有任何转换的情况下进行比较。

  • 只有在运行 Python 3.x 时,将 'u' 更改为 'b' 才会产生任何实际影响

至于直接解决问题,我觉得虽然很清楚你想做什么,但不清楚你为什么选择这样做。为了得到更好的答案,你需要问一个更清楚的问题。

这是另一种方法的示例:

# convert eof markers to a list of characters
eof_markers = {k: list(v) for k,v in eof_markers.items()}

# assuming that the bytes you have read in are being added to a list,
# we can then do a check for the entire EOF string by:

# outer loop reading the next byte, etc, omitted.
for mname, marker in eof_markers.items():
    nmarkerbytes = len(marker) 
    enoughbytes = len(bytes_buffer) >= nmarkerbytes
    if enoughbytes and bytes_buffer[-nmarkerbytes:] == marker:
        location = f.tell()
        print ('%s marker found at %d' % (mname, location))

还有其他更快的方法使用字节或字节数组(例如,使用 'rfind' 方法),但这是最简单的解释方法。

于 2012-09-25T00:55:05.247 回答