【问题标题】:What exactly is the textual representation of Binary data?二进制数据的文本表示究竟是什么?
【发布时间】:2023-03-27 14:30:02
【问题描述】:

有时,当您下载具有错误 mime 类型的已编译二进制文件时,或者例如在二进制文件上运行“更多”命令时,您会因为缺少更好的术语而得到一堆“乱码”。

例如,这是我在 OS X 上用 gcc 编译的一个非常简单的 C 程序的命令行运行“more”时看到的 sn-p。

<94>^^^@^@ESC^@^@^@^^^A^@^@<A8>^^^@^@.^@^@^@^N^D^@^@^P ^@^@@^@^@^@^O^D^@^@^L ^@^@H^@^@^@^O^D^@^@^H ^@^@P^@^@^@^O
^D^@^@^@ ^@^@\^@^@^@^C^@^P^@^@^P^@^@p^@^@^@^O^A^@^@b^_^@^@y^@^@^@^O^D^@^@^D ^@^@<82>^@^@^@^O^A^@^@<B6>^^^@^@<88>
^@^@^@^O^A^@^@T^_^@^@<8D>^@^@^@^O^A^@^@T^^^@^@<93>^@^@^@^A^@^A^B^@^@^@^@<99>^@^@^@^A^@^A^B^@^@^@^@^L^@^@^@^M^@^@
^@ ^@dyld_stub_binding_helper^@__dyld_func_lookup^@dyld__mach_header^@_NXArgc^@_NXArgv^@___progname^@__mh_execute
_header^@_average^@_environ^@_main^@_sum^@start^@_exit^@_printf^@^@^@^@

有人可以简单地解释这是为什么吗?当文本编辑器或纯文本 mime 类型试图解释二进制数据时会发生什么? ^@ 在这种情况下意味着什么吗?为什么有一些文字和一些乱码?这种二进制数据在文本中的表示方式有什么标准吗?为什么不是简单的 1 和 0?

我可以在概念上将 ascii 或 unicode 理解为数字系统中字符的表示,可以简化为二进制 1 和 0 以及 CPU 可以理解的数字系统。但在更高的层次上,我试图弄清楚二进制数据是什么。如果有意义的话,我想我想“看到抽象”。

有没有办法在文本编辑器中以任何有意义的方式“查看”二进制数据?

【问题讨论】:

  • 感谢所有回复的人。只是出于好奇,上述 sn-p 中尖括号代码的含义是什么?例如

标签: text binary


【解决方案1】:

二进制文件和文本文件对于计算机来说都是一回事,毕竟它们都是 0 和 1。您查看文件内容的方式取决于您用来查看文件的程序。
文本编辑器(尝试)将 0 和 1 解释为字符,并向您显示他们得到的字符,您可以将其视为文档。他们假设您提供给他们的文件是包含 ASCII 字符的文本文件。然而,这对于一般的计算机文件来说并非如此,因为它们可以包含任何类型的二进制数据,不一定是 ASCII 字符。发生这种情况时,一些文本编辑器不会给您错误消息,而是给您文件中数据的丑陋和不正确的表示(因为它们无论如何都不理解数据)。
十六进制编辑器更像是极客的工具,因为它们还为您提供十六进制的计算机数据(与二进制相比,这是一种更易读的格式)。一些十六进制编辑器还为您提供他们检测到的 ASCII 字符,因此更方便。
Alex 为您提供了一个非常酷的命令行工具,但如果您想要一些 GUI,一个带有“十六进制编辑器”的快速 google 将为您提供太多许多可供尝试的软件。

【讨论】:

    【解决方案2】:

    除了文件中使用的值范围之外,文本文件和二进制文件之间确实没有显着差异。每个值都会根据使用的代码页(ASCII、ANSI)转换为一个字符(在基本文本编辑器中)。

    您看到字符“^@”是因为文件中该位置的字节值为 0(nul 字符)。 nul 字符不可打印,因此更多程序使用插入符号显示它。

    您可以在十六进制编辑器中打开文件,这是一种对二进制数据更敏感的文本编辑器。我对Mac软件不是很熟悉,但是可以在http://hexedit.sourceforge.net/下载免费的十六进制编辑器。

    基本的文本编辑器/查看器假定您使用它打开的任何内容都将被视为纯文本。

    编辑:合并了 Mike Spross 的更正:^@。

    【讨论】:

    • 我也在试图理解这一点,为什么它完全显示十六进制值?为什么它不简单地显示 1 和 0?另外:如何让它显示 1 和 0?
    • @Nona:我不太了解显示 0 和 1 的程序,但请注意十六进制值(基数 16)是二进制数据(基数 2)的简写。您始终可以将基数为 16 的值转换为其基数为 2 的等效值。只是好奇,但您是否需要出于特定目的查看 0 和 1?
    • 其实^@代表一个'\0'字符(一个值为0的字节)。在 OP 的情况下,更多的是使用插入符号显示文件中的不可打印字符。见en.wikipedia.org/wiki/Caret_notation。
    • @Mike Spross:感谢您的澄清。我已将此详细信息添加到答案中。
    【解决方案3】:

    有没有办法“看到”二进制数据 文本中任何有意义的方式 编辑?

    我建议使用十六进制格式!例如,这些是在 VIM 中编辑二进制文件的建议...:

    使用 XXD

    真正的二进制编辑器显示文本 两种方式:按原样和十六进制格式。 您可以先在 Vim 中执行此操作 使用“xxd”转换文件 程序。这是 Vim 自带的。第一的 以二进制模式编辑文件:

    vim -b 数据文件

    现在将文件转换为十六进制转储 与xxd:

    :%!xxd

    文本将如下所示:

    0000000: 1f8b 0808 39d7 173b 0203 7474 002b 4e49  ....9..;..tt.+NI      
    0000010: 4b2c 8660 eb9c ecac c462 eb94 345e 2e30  K,.`.....b..4^.0      
    0000020: 373b 2731 0b22 0ca6 c1a2 d669 1035 39d9  7;'1.".....i.59. 
    

    您现在可以查看和编辑文本 你喜欢。 Vim 处理信息 作为普通文本。改变十六进制 不会导致可打印字符 改变,或以其他方式 大约。最后转换回来 与:

    :%!xxd -r

    仅使用十六进制部分的更改。 可打印文本部分的更改 右边被忽略了。

    更多信息请参见 xxd 的手册页 信息。

    【讨论】:

    • 感谢 vim 提示和 XXD。在我的调查和好奇心的帮助下。
    【解决方案4】:

    我建议在 Unix 系统上使用 od 命令。它不是一个文本编辑器,但它仍然适用于分析文件的内容。如果大部分字符都是可打印的,您可以使用od -c file。

    乐:GNU od(1) man page

    【讨论】:

      【解决方案5】:

      数据的二进制表示(只有 1 和 0)需要太多的屏幕空间。

      Hex 或 ascii 等价物更简洁,我们的大脑更喜欢这样。

      我们应该将组合的 hex / ascii 显示(例如,由 od 命令生成)视为尝试显示数据看起来像它应该是十六进制数据以及它看起来像它的样子应该是 TEXT。

      但是,正如 Stephen C 所说,没有文本编辑器可以准确地确定字节的含义,所以它只提供了一个提示。

      由用户查看显示并决定数据是文本还是二进制或两者的某种混合

      二进制文件有时包含几组文本字符。特别是如果二进制文件是可执行文件并且必须产生输出。输出消息将作为文本字符序列存储在二进制文件中。能够查看二进制文件中的文本序列是什么以及它们的存储位置非常有用。

      【讨论】:

      • 感谢您的回复。 “我们应该将组合的 hex / ascii 显示(例如,由 od 命令生成)视为尝试显示数据看起来像它应该是十六进制数据以及它看起来像它应该是什么是文本。”我非常喜欢这个解释,用“WOULD”这个虚拟语气。这更加巩固了我的想法。
      【解决方案6】:

      在计算机上,所有数据以二进制形式存储,包括文本文件。这意味着所有内容都使用二进制位存储。只有两个可能的二进制位:一和零。

      文本文件需要区分两个以上不同的符号,因此它将二进制位序列组合成一个更复杂的单元。例如,一个 8 位的序列可以解释为一个 ASCII 字符(值范围从 0 到 255)。

      由于文本文件在内部只是一系列二进制位(一和零),因此任何一系列二进制位都可以解释为文本文件。您示例中的输出是尝试将可执行文件的二进制位解释为文本文件的结果。大多数字符都是垃圾(作为 ASCII 字符序列没有意义),但有些部分是有意义的,因为它们被存储为 ASCII 字符串。

      每种文件格式都有一个二进制位代表的合同。就可执行文件而言,它比简单的文本文件复杂得多,但可执行文件格式还包括存储 ASCII 字符串的部分,就像文本文件一样。

      如果您使用十六进制编辑器查看文件,您可以并排查看文件的二进制表示和二进制的 ASCII 文本解释。请注意,二进制表示以更紧凑的形式显示数据:十六进制。一个 4 位二进制位序列用一个 0 到 F 范围内的十六进制数字表示。

      【讨论】:

      • 感谢 ASCII 解释,您的解释对我来说很有意义。
      【解决方案7】:

      有没有办法“看到”二进制数据 文本中任何有意义的方式 编辑?

      简而言之,没有。二进制数据绝对可以意味着任何东西,一个愚蠢的文本编辑器无法理解它。 (确实,即使是聪明人也无法绝对确定。)

      在 Unix / Linux 系统上处理此问题的正常方法是使用“文件”命令行实用程序。这会查看文件的开头并应用启发式方法为您提供文件类型的“最佳猜测”。在此基础上,您可以查看是否可以找到合适的工具来查看文件内容。如果您没有理解格式的查看器/编辑器/反编译器等,“od”实用程序可以以各种形式向您展示;例如十六进制、八进制、字符等。

      编辑:详细说明“二进制数据绝对可以代表任何东西”:

      • 一种二进制位模式,即 (比如说)编译器的输出不能是 区别于相同 (比方说)输出的二进制位模式 一些随机的用户定义的应用程序。如上所述,如果没有不可逆转的外部流程知识,理论上是不可能区分这些情况的。

      • 识别二进制位模式 (例如,由“文件”程序完成)是 通常基于检测“幻数” 在文件的前几个字节中。例如, 可执行脚本文件的“魔法”是“#!”在 前两个字节。如果你写一个应用程序 生成一个可能有“#!”的二进制文件作为它的第一个 两个字符,这可能会导致“文件”给出错误匹配, 并将您的二进制文件标记为脚本

      因此,从理论和实践的角度来看,任何仅基于其内容的二进制文件类型的识别都是不确定的。

      但即使是某些二进制文件类型也不能解决问题。困难的部分是有人必须为每个二进制文件类型编写一个转换器,它将提取和呈现文件的含义。对于某些文件类型,这些转换器/渲染器已经存在。例如,有许多形式的可执行代码文件格式的反汇编器/反编译器。但是没有适用于所有二进制文件类型的此类转换器,并且确实存在的转换器通常是独立的应用程序,而不是您喜欢的文本编辑器的插件模块。

      【讨论】:

      • 感谢您的回复。 “二进制数据绝对可以表示任何东西,一个愚蠢的文本编辑器无法弄清楚。(事实上,即使是聪明的人也无法绝对确定。)”我认为这是时间和记忆的一个因素。显然,计算机可以更快地分析。所以是的,这对我来说很有意义。
      • @Gordon。我的意思是它实际上是不可知的!二进制数据只是位。如果不知道是什么过程产生了这些比特,理论上不可能确切地知道它们的含义。
      • 如果你能够看到整个结构(例如单个二进制文件),那么结构如何才能理解模式?不?但我想我在这里得到了你更大的观点。翻转一个位,其含义可能会因位在序列中的位置而显着不同。所以这就是不确定性所在。那么这是说处理器在操作上是完全幼稚的吗?一位在下一位之后,处理器仅遵循序列中等待指令的链。
      【解决方案8】:

      您可以将二进制文件视为图像:

      Visualizing binaries with space-filling curves.

      【讨论】:

        猜你喜欢
        • 2010-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-02
        相关资源
        最近更新 更多