二进制数据的文本表示是什么?

5
有时候,当你下载一个带有错误mime类型的编译二进制文件,或者例如在二进制文件上运行"more"命令时,你会看到一堆"乱码",缺乏更好的术语。
例如,当我在OS X上使用gcc编译一个非常简单的C程序并在命令行上运行"more"时,这是我看到的一部分片段。
<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理解的数字系统。但在更高的层面上,我试图理解二进制数据是什么。我想“看到抽象”,如果这有意义的话。
在文本编辑器中,有没有一种有效的方式“看”二进制数据?

感谢所有回复的人。只是出于好奇,上面片段中的尖括号代码是什么意思?例如 <8D> <93> <99> <8D> <93> <99>。 - Gordon Potter
8个回答

4
除了文件中使用的值的范围之外,文本文件和二进制文件之间实际上没有显着的区别。在基本文本编辑器中,每个值都基于使用的代码页(ASCII、ANSI)转换为字符。
你看到字符“^@”,因为文件中该位置的字节值为0(nul字符)。Nul字符不可打印,因此more程序使用插入符号符号表示它。
你可以在十六进制编辑器中打开文件,这是一种对二进制数据更加敏感的文本编辑器。我不太熟悉Mac软件,但可以在http://hexedit.sourceforge.net/下载一个免费的十六进制编辑器。
基本文本编辑器/查看器假定您打开的任何内容都是纯文本。

我也在尝试理解这个问题,为什么它会显示十六进制值?为什么不直接显示1和0呢?另外,我该如何让它显示1和0? - Nona Urbiz
@Nona:我不太清楚有哪些程序可以显示0和1,但请注意十六进制值(基数16)是二进制数据(基数2)的简写。您可以将基数16的值转换为其基数2的等效值。只是好奇,您需要看到0和1以达到特定目的吗? - David Andres
3
实际上,^@ 表示一个 '\0' 字符(一个值为0的字节)。在此代码片段中,more 命令使用脱字符表示法来显示文件中的不可打印字符。参见 http://en.wikipedia.org/wiki/Caret_notation。 - Mike Spross
@Mike Spross:感谢您的澄清。我已将此细节添加到答案中。 - David Andres

4
计算机对于二进制文件和文本文件来说,它们都是0和1。您看到文件内容的方式取决于您用于查看文件的程序。 文本编辑器会(尝试)将0和1解释为字符,并显示它们获取的字符,您可以将其视为文档。它们假设您提供给它们的文件是文本文件,包含ASCII字符。但是,这并不适用于计算机文件总体而言,因为它们可能包含任何类型的二进制数据,而不一定是ASCII字符。当发生这种情况时,有些文本编辑器不会向您显示错误消息,而是会给您一个丑陋且不正确的文件数据表示(因为它们无法理解该数据)。 十六进制编辑器更多是极客的工具,因为它还以十六进制形式(与二进制相比更易读)提供计算机数据。一些十六进制编辑器还会向您提供它们检测到的ASCII字符,因此更加方便。 Alex给出了一个非常酷的命令行工具,但如果您想要一些图形用户界面,快速使用“十六进制编辑器”进行谷歌搜索将为您提供太多软件供您尝试。

3
有没有一种方法可以在文本编辑器中以有意义的方式“查看”二进制数据?
我建议使用十六进制格式!例如,在VIM中编辑二进制文件的建议是...:
使用XXD 真正的二进制编辑器以两种方式显示文本:原样和十六进制格式。您可以通过首先使用“xxd”程序将文件转换来在Vim中执行此操作。这是随Vim提供的。首先以二进制模式编辑文件: vim -b datafile 现在使用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的帮助,让我在调查和好奇心的驱使下更加得心应手。 - Gordon Potter

1

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

LE: GNU od(1) man page


1
有没有一种方法可以在文本编辑器中以任何有意义的方式“查看”二进制数据?
简而言之,没有。二进制数据可以意味着绝对任何东西,愚蠢的文本编辑器无法弄清楚它。 (实际上,即使是聪明的人也不能绝对确定。)
在Unix / Linux系统上处理这个问题的常规方法是使用“file”命令行实用程序。它查看文件开头并应用启发式方法,为您提供文件类型的“最佳猜测”。基于此,您可以查找适当的工具来查看文件内容。如果您没有了解该格式的查看器/编辑器/反编译器等,则“od”实用程序可以以各种形式向您显示它;例如十六进制,八进制,字符等。
编辑:详细说明“二进制数据可以意味着绝对任何东西”:
  • 一个二进制位模式,例如编译器输出的模式和某个随机用户定义应用程序输出的完全相同的二进制位模式是无法区分的。理论上,如果没有不可争辩的外部知识来了解这个过程,就无法区分这两种情况,正如我之前所述。

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

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

但是,即使是某些二进制文件类型也无法解决问题。难点在于某个人必须为每种二进制文件类型编写一个转换器,以提取和呈现文件的含义。对于某些文件类型,这些转换器/渲染器已经存在。例如,有许多可执行代码文件格式的反汇编器/反编译器。但并非所有二进制文件类型都有这样的转换器,而且现有的转换器通常是独立的应用程序,而不是您喜爱的文本编辑器的插件模块。


谢谢您的回复。"二进制数据可以意味着绝对任何东西,而愚蠢的文本编辑器无法找出任何方法。(事实上,即使是聪明的人也不能以绝对的确定性找出它的含义。)" 我想这是时间和内存的一个因素。显然电脑可以分析得更快。所以,是的,这对我来说是有道理的。 - Gordon Potter
1
@Gordon。我的意思是它从本质上来说是无法知道的!二进制数据只是位。如果不知道生成这些位的过程,理论上就不可能确定它们的含义。 - Stephen C
如果您能够看到整个结构(例如一个单一的二进制文件),那么模式就能被理解了,不是吗?但我想我明白了你的大意。如果翻转一个单独的位,取决于这个位在序列中的位置,它的含义可能会戏剧性地发生改变。所以这就是不确定性所在的地方。那么这是否意味着处理器在操作上完全是天真的?一个位跟随另一个位,处理器只是按照顺序跟随这个链,等待指令的到来。 - Gordon Potter

1

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

十六进制或ASCII等价物更为简洁,而且我们的大脑更喜欢这样。

我们应该将组合的十六进制/ ASCII显示(例如od命令生成的)视为尝试展示数据如果是十六进制数据和文本数据时会是什么样子。

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

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

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


感谢您的回复。"我们应该将组合的十六进制/ ASCII 显示(例如由 od 命令生成)视为尝试显示数据如果它是十六进制数据和如果它是文本数据时的样子。"我非常喜欢这个解释,特别是用了虚拟语气的“WOULD”。这让我更加明确了一些事情。 - Gordon Potter

1
在计算机上,所有数据都以二进制形式存储,包括文本文件。这意味着所有内容都是使用二进制位存储的。只有两种可能的二进制位:1和0。
文本文件需要区分超过两个不同的符号,因此它将一系列二进制位组成更复杂的单元。例如,8位序列可以解释为一个ASCII字符(值范围从0到255)。
由于文本文件内部只是一系列二进制位(1和0),因此任何一系列二进制位都可以被解释为文本文件。你的例子中的输出结果是试图将可执行文件的二进制位解释为文本文件的结果。大多数字符都是垃圾(作为ASCII字符序列没有意义),但其中一些部分是有意义的,因为它们被存储为ASCII字符串。
每种文件格式都有一个二进制位表示的协议。在可执行文件的情况下,它比简单的文本文件复杂得多,但可执行文件格式也包括像文本文件一样存储ASCII字符串的部分。

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


感谢您对ASCII的解释,您的解释让我很容易理解。 - Gordon Potter

0

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