【问题标题】:Why and how should I write and read from binary files?为什么以及如何读写二进制文件?
【发布时间】:2013-01-16 23:58:49
【问题描述】:

我正在编写一个游戏项目作为一种爱好,目前我需要将一些资源数据(例如 .BMP)存储为我自己的文件格式,以便我的游戏可以解析所有这些数据并加载到屏幕中。

为了读取 BMP,我先读取标题,然后读取每个像素的 RGB 数据,然后我有一个数组[width][height] 来存储这些值。

有人告诉我应该将这些类型的数据保存为二进制,但不是原因。我已经阅读了二进制及其是什么(数据的 0-1 表示),但我为什么要使用它来保存 .BMP 数据? 如果我稍后在游戏中阅读它,它不是只会增加更多的复杂性,甚至可能会减慢加载过程吗?

最后,如果最好保存为二进制文件(我猜是这样,从我在其他游戏资源文件中研究的内容来看,每个人似乎都是这样做的)我如何在 C++ 中读取和写入二进制文件? 我已经看到了很多问题,但是对于许多不同类型的变量有很多不同的方法,所以我想问哪种方法是最好的/更像 C++ 的方法?

【问题讨论】:

  • bmp 是一种其他人可以使用的具有规范的格式,如果您想使用它,您需要以该格式编写,以便其他通常可以打开 bmp 文件的程序也可以读取它们。如果您只想能够读取这些文件,请将其保存为您想要的任何格式,但不要以人们可能会将它们误认为其他格式的方式命名文件。
  • 这里的二进制很可能意味着不是文本。

标签: c++ binary binaryfiles


【解决方案1】:

一切都倒退了。计算机处理器处理二进制级别的数据。计算机中的一切都是二进制的。为了以人类可读的形式处理数据,我们编写了一些函数,这些函数可以跳过箍,使二进制数据看起来像人类可以理解的东西。因此,如果您将 .BMP 数据作为文本存储在文件中,您实际上会让计算机做更多的工作来将 .BMP 数据从其自然二进制形式转换为文本,然后再从其文本形式转换回二进制为了显示它。

事实是,您处理原始二进制形式的数据越多,您的代码运行速度就越快。更少的转换意味着更快的代码。但显然有一个折衷:如果您需要能够查看数据并理解它而不需要拿出一个神奇的解码器环,那么您可能希望将它作为文本存储在一个文件中。但在这样做时,我们必须了解必须进行转换处理才能使人类可读的文本对处理器有意义,正如我所说,处理器只对纯二进制数据进行操作。


并且,以防万一您已经知道或知道它,而您的问题是“为什么我应该以二进制模式而不是文本模式打开我的 .bmp 文件”,那么原因是以文本模式打开文件要求平台根据平台执行必要的 CRLF 到 LF 转换(“\r\n”到-“\n”转换),以便在内部字符串处理级别,您所处理的只是 '\n' 个字符。如果您的文件包含二进制数据,则您不希望继续进行该转换,否则它会在您读取文件时损坏文件中的数据。在这种状态下,大部分数据都可以正常工作,并且大部分时间都可以正常工作,但有时您会遇到一对十六进制形式 0x0d,0x0a(十进制 13,10)的字节,它们将被转换到只有 0x0a (10),你会在你读取的数据中丢失一个字节。所以一定要以二进制模式打开二进制文件!


好的,根据您最近的评论(如下),这是:

正如您(现在?)所了解的,计算机中的数据以二进制格式存储。是的,这意味着它在 0 和 1 中。但是,在编程时,您实际上不必自己摆弄 0 和 1,除非出于某种原因您正在执行按位逻辑运算。一个类型的变量,比如int,是单个位的集合,每个位可以是 0 或 1。它也是字节的集合,假设一个字节中有 8 个位,那么通常是 int 中的 2、4 或 8 个字节,具体取决于您的平台和编译器选项。但是您将 int 用作 int,而不是单独的 0 和 1。如果您将int 以其最纯粹的形式写入文件,则字节(以及位)将以未转换的原始形式写入。但是您也可以将它们转换为 ASCII 文本并以这种方式写出来。如果您在屏幕上显示int,您当然不想看到单独的 0 和 1,因此您以 ASCII 格式打印它,通常解码为十进制数。您可以轻松地以十六进制形式打印相同的int,即使它是相同的数字,结果也会看起来不同。例如,在十进制中,您可能有十进制值 65。同样的十六进制值是 0x41(或者,如果我们知道它是以 16 为基数的,则只有 41)。如果我们以 ASCII 格式显示,则相同的值就是字母“A”(并且只考虑 2、- 4、- 或 8 字节 int 的低字节,即将其视为 char)。

在接下来的讨论中,忘记我们讨论的是int,现在考虑我们讨论的是char,即1 字节(8 位)。假设我们仍然有相同的值,65,或 0x41,或“A”,但是您想查看它。如果您想将该值发送到文件,您可以将其以原始形式发送,也可以将其转换为文本形式。如果以原始形式发送,它将占用文件中的 8 位(一个字节)。但是,如果您想以文本形式将其写入文件,则将其转换为 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 个字节(或 4,如果我们在前面加上“0x”),因为十六进制的值 255 是 0xFF。将此与以原始二进制形式写入 8 位字节 (char) 进行比较:char 占用 1 个字节(根据定义),因此无论其值如何,它都只会以二进制形式消耗文件的 1 个字节是。

【讨论】:

  • 我明白了,谢谢你的信息。但是,如果我要用图像中的 RGB 信息填充我的数组 [宽度] [高度],我不需要将其转换为可读格式以便正确填充数组吗?或者我应该为这些操作使用 0-1s 吗?我猜我需要将二进制转换为 char(0-255 范围)的值。
  • 是的,我明白了用二进制文件写的好处,非常感谢!我搜索过的大多数地方都给了我相同的定义,但我无法理解从中节省空间的好处。
  • @Danicco - 这不是一个“节省空间”的问题,尽管这确实有好处,因为它是一个“不必执行任何转换”的问题。此外,如果您自己将位图存储在文件中,您可能希望让您的程序以真正的 .bmp 格式写入和读取位图,这样您就可以轻松地换出图像等。如果您正在倾倒一堆杂七杂八的东西但是,在单个文件中,显然这并不重要。
  • @Danicco - 实际上,我收回了这一点。这与其说是一个“节省空间”的问题,不如说是一个“更少的文件 I/O”问题。读写文件所涉及的 I/O 越少,运行速度就越快。是的,不必将 ASCII 转换为原始数据会有所帮助,但我认为更大的问题是必须读取和写入额外字节的文件 I/O 负担。
猜你喜欢
  • 1970-01-01
  • 2012-01-26
  • 2018-07-26
  • 2016-06-14
  • 2021-06-03
  • 1970-01-01
  • 1970-01-01
  • 2019-04-20
相关资源
最近更新 更多