【问题标题】:Find Binary Value Within ASCII String在 ASCII 字符串中查找二进制值
【发布时间】:2014-09-16 11:02:34
【问题描述】:

我有一个数据文件,在打印时会输出一系列字符:

@ao��B��@�a��z�I{�@�M�C�cID ...等

我还有一个从该数据文件中提取的二进制值,但我不确定文件中的哪个位置。因此,鉴于我可以使用

读取数据
  with open(self.filename, mode='rb') as data_file:
                self._file_contents = data_file.read()

我一直在尝试在表示文件的大字符串中搜索二进制值的索引起始位置。

[m.start() for m in re.finditer(binary, data_file._file_contents]

我已尝试将binary 作为二进制字符串(例如10011010)并使用str(int(binary,2)) 将其转换为可在文件中搜索的整数字符串值。 这些都没有奏效,所以我在质疑自己的逻辑和理由。如果您知道如何找到二进制值的索引,假设您 100% 确定它在文件中,请告诉我您将如何做到这一点。谢谢

【问题讨论】:

  • 我认为您在这里混淆了“二进制”的两个含义:数字的 base-2 表示(例如 10011010 是二进制的 154)与“非文本”(例如 @987654326 Python 3 中的 @ 或 Python 2 中的 '@ao��' 是字节或字符串中的二进制数据。
  • 能否请您扩展“字节或字符串中的二进制数据”?
  • bytes/str 对象的内容有时会被解释为编码(或只是 ASCII)文本,例如 b"Foo: bar\n",但它们有时也不是 旨在解释为文本,如 "@ao��",或 JFIF 图像的内容。后一种情况称为“二进制数据”。它不是二进制的,因为它是 base-2,它是二进制的,因为它的含义是非文本的。

标签: python string binary full-text-search ascii


【解决方案1】:
binary = "\x22"  # <- this is what binary should look like
[m.start() for m in re.finditer(binary, data_file._file_contents)]

如果您的 intvalue 为 77,则可以使用 binary = chr(77) 进行转换

如果你有十六进制值77=0x4d,你可以做binary="\x4d"

如果值大于 0xff,则需要 unichar binary = unichr(257) 并且您将需要使用 unicode 字符串 (257=0x0101) binary = u"\u0101"binary="\x01\x01"

【讨论】:

  • 如何将其转换为 "\x22" 形式?这个表格到底是什么?数据为 32 位切片,因此最大值为 0xffffffff,这些切片全部连接并存储在原始数据文件中。因此,例如,鉴于文件中的大字符串以@ao��B 方式格式化,我希望在大字符串中找到 0xffffffff 或 1111...111 或 4294967295?感谢您的帮助
  • � 没有帮助,因为它什么也没告诉我们……要查看数据的实际样子,请使用repr(data_file.read()),它会显示二进制转义序列……所以如果你想找到@ 987654330@ ,然后二进制将是 binary="\xff\xff\xff" 因为在字符串(或字节数组)中,每个“字符”或字节只有一个字节宽(即 0x00-0xff
  • 所以最好的做法是将二进制值(例如 10011)转换为十六进制,从那里转换为 "\xff\xff\xff" bytearray 样式,然后搜索它在 repr(data_file._file_contents) 中?
  • 更多所以我想知道是否有更直接的方法以“\xff\xff\xff”形式获取它?
  • 除非您碰巧知道该值将是 32 位对齐的,否则此答案的 Unicode 部分不起作用(因为 Unicode 正则表达式不会搜索一个字符的一半和下一个字符的一半),并且您的平台对 Unicode 使用 UTF-32 而不是 UTF-16。
【解决方案2】:

更多所以我想知道是否有更直接的方法以“\xff\xff\xff”形式获取它?

是的。这种事情正是struct 模块的用途:

>>> import struct
>>> struct.pack('<I', 4294967295)
'\xff\xff\xff\xff'
>>> struct.pack('<I', 1234567)
'\x87\xd6\x12\x00'

但这里的重要部分是您必须知道要查找的格式。上面的代码将每个数字视为 little-endian 无符号 32 位 C 整数,这是将数字塞入二进制数据的一种非常常见的格式,但肯定不是唯一的。

如果你想用十六进制(以 16 为底)或二进制(以 2 为底)而不是十进制来编写文字值,当然可以;就 Python 而言,0b1001113 是同一个东西——数字 13。所以:

>>> struct.pack('<I', 0b10011)
'\x13\x00\x00\x00'
>>> struct.pack('<I', 0xabcd)
'\xcd\xab\x00\x00'

但是,如果您拥有以 2 为底的数字的唯一原因是您调用了某个将数字转换为以 2 为底的表示的函数,那么请不要调用该函数。

【讨论】:

    猜你喜欢
    • 2021-12-01
    • 1970-01-01
    • 2014-01-14
    • 1970-01-01
    • 2012-08-02
    • 1970-01-01
    • 1970-01-01
    • 2014-06-14
    • 1970-01-01
    相关资源
    最近更新 更多