你完全弄反了。计算机处理器以二进制级别操作数据。在计算机中,一切都是二进制的。为了处理人类可读格式的数据,我们编写函数来跳过许多步骤,使二进制数据看起来像人类所理解的东西。因此,如果你将.BMP数据存储为文本文件,则实际上是让计算机做更多的工作,将.BMP数据从其自然的二进制形式转换为文本,然后从文本形式转换回二进制以显示它。
事实是,你越能处理原始二进制形式的数据,你的代码运行得越快。少进行转换意味着更快的代码。但显然存在一个权衡:如果你需要查看数据并理解它而不必拿出魔法解码器环,那么你可能希望将其存储为文本文件。但这样做时,我们必须了解,必须进行转换处理,以使人类可读的文本对处理器有意义,而处理器只处理纯二进制数据。
另外,如果你已经知道这一点或者大致知道这一点,并且你的问题是“为什么应该以二进制模式而不是文本模式打开我的.bmp文件”,那么这是因为以文本模式打开文件会要求平台执行CRLF到LF的转换(根据平台需要),以便在内部字符串处理级别上,你所处理的只是'\n'字符。如果文件由二进制数据组成,你不希望发生这种转换,否则它将在读取时破坏文件中的数据。在这种状态下,大多数数据都没问题,而且大部分时间都可以正常工作,但偶尔你会遇到一对十六进制形式为0x0d、0x0a(十进制13、10)的字节,它们将被转换为仅为0x0a(10),并且你将丢失读取的一个字节的数据。因此,请务必以二进制模式打开二进制文件!
正如你现在明白的那样,计算机中的数据以二进制格式存储。是的,这意味着数据由0和1组成。但是,在编程时,你通常不需要直接处理0和1,除非你因某种原因要进行按位逻辑操作。例如,类型为
int
的变量是一组单独的位,每个位可以是0或1。它也是一组字节,假设每个字节有8个位,则
int
通常由2、4或8个字节组成,具体取决于您的平台和编译器选项。但是,您把
int
看作一个整体,而不是单独的0和1。如果您将该
int
以最纯净的形式写入文件,则字节(因此也是位)以未转换的原始形式写出。但是,您也可以将它们转换为ASCII文本并以这种方式写出。如果您在屏幕上显示
int
,您肯定不想只看到单独的0和1,因此您会按其ASCII形式打印它,通常解码为十进制数。您同样可以将相同的
int
以其十六进制形式打印出来,即使是相同的数字,结果看起来也会有所不同。例如,以十进制表示,您可能有十进制值65。同样的值在十六进制中为0x41(或者如果我们知道它是基于16进制的,则只需写为41)。如果我们以ASCII形式显示它(并且仅考虑2、4或8字节的低字节,即将其视为一个
char
),则相同的值是字母'A'。
在接下来的讨论中,忘记我们之前提到的是一个
int
,现在假设我们正在讨论的是一个
char
,也就是 1 个字节(8 个比特)。假设我们仍然有同样的值,65、0x41 或 'A',怎么看都可以。如果你想将这个值发送到文件中,你可以以其原始形式发送,也可以将其转换为文本形式发送。如果你以原始形式发送,它将占用文件中的 8 个比特(1 个字节)。但如果你想以文本形式将其写入文件,则需要将其转换为 ASCII 码,具体取决于你要写入的格式和实际值(在这种情况下为 65),它将占用 1、2 或 3 个字节。比如说,如果你想以十进制 ASCII 码形式不带填充字符地将其写入,那么值 65 将占用 2 个字节:一个用于 '6',一个用于 '5'。如果你想以十六进制形式打印它,它仍将占用 2 个字节:一个用于 '4',一个用于 '1',除非你在前面加上 "0x",此时它将占用 4 个字节,一个用于 '0',一个用于 'x',一个用于 '4',还有一个用于 '1'。或者假设你的
char
的值是 255(
char
的最大值):如果我们以十进制 ASCII 码形式将其写入文件,它将占用 3 个字节。但是,如果我们以十六进制 ASCII 码形式写入相同的值,它仍然只占用 2 个字节(如果我们在前面加上 "0x",则为 4 个字节),因为十六进制中的值 255 是 0xFF。将此与以原始二进制形式写入 8 位比特(
char
)进行比较:按定义,一个
char
占用 1 个字节,因此无论其值如何,在二进制形式下,它仅占用文件的 1 个字节。