c++ - 将数字数据写成二进制还是写成二进制?

标签 c++ file 3d numbers file-writing

我正在将浮点数写入文件,但是有两种不同的方式写入这些数字,我想知道该使用哪种方式。

两种选择是:

  • 将原始代表位写入文件
  • 将数字的ascii表示形式写入文件

  • 选项1似乎对我来说更实用,因为我将每个float都截断为4个字节。阅读时可以完全跳过解析每个数字的操作。但实际上,我只见过使用选项2。

    有问题的数据是3D模型信息,在这种情况下,较小的文件大小和快速读取可能会非常有优势,但是同样,据我所知,没有任何现有的3D模型格式可以做到这一点,并且我想背后必须有充分的理由。

    我的问题是,选择书写数字形式而不是位表示形式的原因有哪些?在某些情况下,首选使用二进制形式吗?

    最佳答案

    首先,float在您可能会遇到的任何体系结构上均为4个字节,因此,当您将4个字节的内存从文件写入文件时,不会被“截断”。

    关于您的主要问题,许多常规文件格式都是为“互操作性”和易于读取/写入而设计的。这就是为什么文本(几乎是通用的可移植表示形式(尽管存在字符编码问题))被最常使用的原因。

    例如,程序很容易从文本文件中读取字符串“123”,并知道它代表数字123。

    (但请注意,文本本身不是一种格式。您可以选择将所有数据元素表示为ASCII / Unicode /任何字符串,并将所有这些字符串相互组合以形成文本文件,但仍然需要确切指定每个元素的含义以及可以在何处找到哪些数据,例如,一种非常简单的基于文本的3D三角形网格文件格式可能在文件的第一行中具有网格中的三角形数量,然后是三个三元组接下来的N行上的实数,每行指定一个三角形的三个顶点的X,Y,Z坐标所需的9个数字。)

    另一方面是二进制格式。它们中通常包含与计算机内存中相同格式的数据元素。这意味着整数用固定数量的字节表示(1、2、4或8,通常采用“二进制补码”格式),或者实数由IEEE 754格式的4或8个字节表示。 (请注意,为了保持重点,我省略了很多细节。)

    二进制格式的主要优点是:

  • 它们通常较小。以ASCII字符串写入的32位整数最多可以获取10或11个字节(例如-1000000000),但是以二进制形式,则始终占用4个字节。较小的体积意味着更快的传输速度(通过网络,从磁盘到内存等)并且易于存储。
  • 每个数据元素的读取速度都更快。无需复杂的解析。如果数据元素恰好是平台/语言可以使用的正确格式/布局,那么您只需要将少量字节从磁盘传输到内存就可以了。
  • 即使大型复杂的数据结构也可以按照与存储在内存中完全相同的方式放置在磁盘上,然后您要做的“读取”该格式的所有操作就是获取大的字节(一次简单,快速的操作就可以将磁盘中的许多数据元素(从磁盘存储到内存中)完成。

  • 但是,第三项优势要求您将磁盘上数据的布局(逐位)与内存中数据结构的布局完全匹配。这意味着,几乎总是,该文件格式仅适用于您的代码和仅适用于您的代码,即使您在自己的代码中进行了一些更改,也无法使用。这意味着它根本不是便携式的或不能互操作的。但是,该死的工作起来真是太快了!

    二进制格式也有缺点:
  • 您再也无法在简单的通用软件(如文本编辑器)中查看或编辑或理解它们。您可以在任何文本编辑器中打开任何XML,JSON或配置文件,并相当容易地理解它,但不能是JPEG文件。
  • 通常,与文本格式相比,您需要更具体的代码来读/写二进制格式。更不用说说明该文件的每一位应该是什么的规范。文本文件通常更加不言自明。
  • 在某些(许多)语言(脚本语言和“高级”语言)中,您通常无法访问组成整数或浮点数的字节,既无法读取它们也无法编写它们。这意味着当您使用诸如C或C++之类的较低级语言工作时,您将失去二进制文件给您的大部分速度优势。
  • 基本数据类型的二进制内存格式几乎总是与内存所连接的硬件(或更普遍地说,整个平台)相关联。当您选择将内存中的相同位写入文件时,文件格式也将取决于硬件。一种硬件可能不会以与另一种完全相同的方式存储浮点实数,这意味着写在一种硬件上的二进制文件不能天真地在另一种上读取(必须小心,并且将数据仔细转换为目标格式)。硬件体系结构之间的关系称为“字节序”,它会影响多字节原语(例如4字节整数或8字节浮点数)在内存中的存储方式(从最高位字节到最低位,反之亦然)反之亦然,分别称为“big endian”和“little endian”。)在big-endian体系结构(例如PowerPC)上写入二进制文件并在little-endian体系结构(例如x86)上逐字读取的数据将具有所有每个基元中的字节从高值转换为低值,这意味着所有(几乎所有)值都是错误的。

  • 既然您提到了3D模型数据,那么让我给您提供一个示例,说明典型游戏引擎中使用的格式。游戏引擎运行时很可能需要读取模型时所能拥有的最快速度,并且3D模型很大,因此通常其模型文件具有非常特定且并非一成不变的格式。但是这种格式很可能不受任何建模软件的支持。因此,您需要编写一个转换器(也称为导出器或导入器),该转换器将采用通用的通用格式(例如OBJ,DAE等)并将其转换为引擎特定的专有格式。但是正如我提到的那样,使用基于文本的格式进行读取/传输/处理比使用二进制格式更容易,因此您通常会选择基于文本的通用格式来将模型导出到其中,然后在它们上运行转换器以进行优化,二进制,特定于引擎的运行时格式。

    关于c++ - 将数字数据写成二进制还是写成二进制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31362637/

    相关文章:

    php - 将数组转换为 .txt 文件

    python - Python 中的 4D 密度图

    math - 如何计算相机的 z 距离以在 3D 空间中以 100% 的原始比例查看图像

    c++ - 忽略 `Wunused-parameter`作为第三方标题

    java - 如何访问外部文件夹(Web 服务器)?

    将 ASCII 数字转换为其 ASCII 字符代码 - C(不打印!)

    javascript - THREEJS Outer Glow to Plane 基元

    c++ - 将函数指针作为参数传递给 std::bind 中的另一个函数

    c++ - 如何通过 Boost.MPI 发送 2d Boost.MultiArray 的子数组?

    c++ - McCabe 的圈复杂度