在许多项目中,我看到数据对象/结构以二进制模式写入文件,然后再以二进制模式从文件中检索回来。
我想知道为什么他们在二进制模式下这样做?文本和二进制模式之间的任何性能差异?如果没有,那么何时使用二进制模式或文本模式?
答案 0 :(得分:16)
二进制更快。考虑一个以32位(4字节)存储的整数,例如123456.如果你把它写成二进制(这是它在计算机中的表示方式),则需要4个字节(忽略项目之间的填充以便在结构中对齐) )。
要将数字写为文本,必须将其转换为字符串(转换的一些开销和存储的内存),然后将其写出来,至少需要6个字节,因为有6个字符需要重新存在数字。这不包括任何额外的填充,例如用于对齐的空间或用于读取/分离数据的分隔符。
现在,如果你考虑它你有几千个项目,额外的时间可以累加并需要更多的空间,这需要更长的时间来读入,然后有额外的时间转换回二进制存储后你有将值读入内存。
文本的优点是,它更容易为人阅读,而不是尝试读取数据的二进制数据或十六进制转储。
答案 1 :(得分:6)
如果您的程序是唯一要使用该文件的程序,您可以使用二进制文件“按原样”保存内部结构。
但是,如果您想与其他程序或互联网交换文件,那么二进制格式就不那么好了。想想关于big-endian与little-endian机器的问题的例子。此外,文件或数据的接收者很可能无法访问您的代码和结构,因此基于文本的格式可能更容易解析并实现到自己的结构中。
关于性能,确实直接读取和编写内部结构会更快,因为您不必将它们(也称为编组)转换为另一种格式。
答案 2 :(得分:5)
历史上,二进制模式是提供或多或少的透明访问
到底层流;文本模式"规范化"标准文本
表示,其中行由单个'\n'
终止
字符。此外,系统可能会对大小施加限制
二进制文件的例子,例如要求它是128或的倍数
512字节。 (第一个是CP / M的情况,是许多人中的第二个
DEC OS的。)文本文件没有这个限制,并且在这种情况下
操作系统强加它,图书馆通常会引入额外的
文本文件的文件结尾字符。 (即使在今天,大多数Windows
当读取文本时,库识别文件的旧CP / M结尾0x1A
模式。)由于这些考虑,文本模式仅定义
一组有限的二进制值。 (但是如果你把200个字节写入二进制文件
文件,重读时可能会返回256或512。从历史上看,
二进制只应该用于其他结构化的文本,所以
你可以识别逻辑结束,并忽略这些额外的
字节)。
此外,您可以在以二进制文件打开的文件中任意搜索 模式;你只能寻求开始,或寻找你所处的位置 以前记忆,在文本模式。 (这是因为该行结束 映射意味着位置之间没有简单的关系 在文件中,以及文本流中的位置。)
请注意,这与输出是否格式正交:
如果使用<<
输出(并使用>>
输入),则格式化IO,
无论文件打开的模式如何。和格式化
总是文字; iostreams旨在操纵流
文本,并且对非文本输入和输出的支持有限。
今天,情况有所改变:在许多情况下,我们期待什么 我们写的是可以从其他机器读取,这假设一个井 定义的格式,可能不是本机使用的格式。 (因此,为 例如,Internet期望两个字节序列0x0D,0x0A作为一行 结束,这与Unix内部使用的内容不同 其他操作系统。)如果可移植性是一个问题,你通常定义一个 格式,明确写它,并使用二进制模式来确保你 写正是写的;类似的输入,你使用二进制 格式化,并手动处理约定。如果您只是写信给 一个本地磁盘,不是共享的,但是,文本模式很好,有点 减少工作量。
同样,这两个都适用于文本。如果你想要二进制格式,你
必须使用二进制模式,但这远远不够。你必须这样做
自己实现所有格式化的IO。在这种情况下,我一般
不要使用std::istream
或std::ostream
(其抽象是文本),
而是定义我自己的流类型,派生自std::ios_base
(对于错误处理约定),并使用std::streambuf
(for
物理IO)。
最后,不要忽视所有 IO格式化的事实 方式。只需将一块内存写入文件即可 格式是当前实现恰好给你的东西(哪个 通常没有证件,这意味着你可能无法胜任 将来阅读它。如果你所做的只是溢出到磁盘,和 你读它的唯一一次是使用相同的程序,用。编译 相同版本的相同编译器,使用相同的编译器选项 如果有问题的内存只是POD,你可以转储内存 并且不包含指针。否则,您必须定义(和文档) 您使用的格式,并实现它。在这种情况下,我建议使用 现有的格式,如XDR,而不是发明自己的格式:它很多 更容易编写&#34;使用XDR格式&#34;作为文档,而不是 描述所有不同的实际位和字节布局 类型。
答案 3 :(得分:3)
如果您以文本模式读取/写入文件,则表示您正在操作文本。它可能是编码错误和特定于操作系统的格式更改的主题,但有时它可能正常工作。但是,在二进制模式下,您将无法满足这些限制。此外,文字模式可能会对\n
个字符执行有趣的操作,例如将其替换为\n\r
。
Fopen引用说:
在文本文件的情况下,取决于所在的环境 应用程序运行时,可能会发生一些特殊字符转换 输入/输出操作以使它们适应系统特定的文本文件 格式。在许多环境中,例如大多数基于UNIX的系统,它 将文件作为文本文件或二进制文件打开没有区别; 两者的处理方式完全相同,但区别在于 建议更好的便携性。
答案 4 :(得分:2)
二进制和文本模式之间的选择只会影响少数操作系统。 Unix或Linux系统都没有为文本模式做任何特殊操作 - 也就是说,text与binary相同。
Windows和VMS特别是以文本模式转换数据。在写入文件时,Windows会将\n
转换为\r\n
,而在阅读时则转换为\n
。 VMS具有要观察的文件记录结构,因此在默认模式下,它将{{1}}转换为记录分隔符。
在不同的地方,二进制更快。如果它没有区别,那就没有区别了。
答案 5 :(得分:2)
在二进制模式下,您可以使用字节大小(考虑256),在文本模式下,它的大小不超过100个字符。显然,您将获得超过两倍的存储数据大小。
此外,您还必须遵守结构规范,例如IPv4等网络数据包。
让我们举个例子
//No padding
typedef struct abc
{
int a:4
char b;
double c;
} A[]={{.a=4,.b='a',.c=7.45},{.a=24,.b='z',.c=3.2}} ;
在文本模式下存储位字段并不困难。显然你会丢失很多东西。
但是,您可以像使用MIME一样以文本格式保存数据对象,但是需要额外的例程才能以二进制模式进行转换;表现受到了打击。
答案 6 :(得分:0)
二进制格式对于存储数字更准确,因为它们存储在精确的内部表示中。保存数据时没有对话,因此保存速度要快得多。