首页 > 解决方案 > fread 和 fwrite 如何区分 C 中的不同数据(类型)?

问题描述

我正在使用一个程序和 C(使用 Ubuntu 及其 bash)并使用它来操作二进制数据文件。首先,当我使用fopen(filename, 'w')它时,它会创建一个文件,但没有任何扩展名。但是,当我使用vim filename它时,它会以某种二进制形式打开。

对于这个问题,当我使用fwrite(array, sizeof(some struct), # of structs, filePointer)它时,它会将(我不确定二进制如何)写入文件。当我使用fread(anotherArray, sizeof(same struct), same # of structs, anotherFilePointer)它时,我神奇地知道如何以二进制形式读取每个结构并将其放入数组中,只需知道它的大小和要读取的数量。如果我输入的十进制值小于# of structs参数中的结构数会怎样?怎么会fread知道正确阅读什么?它如何仅通过查看大小而不知道它是什么类型的数据来读取数据?

标签: cstruct

解决方案


fwrite将存储对象的内存字节写入输出流,fread并将输入流中的字节读取到它作为参数获取的地址的内存中。不对存储在该内存中的 C 对象的类型和表示进行任何假设。

因此会出现很多问题:

  • 基本类型的表示可能因一种编译器而异,一种机器与另一种机器不同,一种操作系统与另一种不同,甚至可能取决于编译器开关。仅当您知道将文件读回字节兼容结构时,写入基本类型的内存表示的字节才有意义。
  • 访问输入和输出文件的模式很重要:正如您所提到的,文件必须以二进制模式打开,以避免内存表示和文件内容之间的任何转换,例如遗留系统上的文本文件发生的情况。例如,MS-Windows 上的文本模式导致0A字节在输出时转换为0D 0A序列,而字节在输入时被剥离,从而导致初始内容0D中孤立字节的内容不同。0D
  • 如果 C 结构包含指针,则写入输出的字节表示这些指针的,而不是它们指向的值。将这些值读回内存很可能会创建无效指针,并且不太可能产生任何意义。
  • 如果 C 结构末尾有一个灵活数组,则其内容不包含在由写入或读取的sizeof(T)字节中。fwritefread
  • C 结构可能包含成员之间的填充,导致输出文件包含不确定的字节,这在某些情况下可能是一个问题。
  • 如果 C 结构的数组只有部分有意义的内容,例如char包含 C 字符串的数组,请注意fwrite将写入超出空终止符的字节,这应该没有意义,但可能是敏感信息,例如密码片段或其他有意义的数据。仔细擦除此类数组可能会避免此问题,但填充字节无法可靠擦除,因此此解决方案并不完美。

由于上述所有原因和其他原因,读取/写入二进制数据将保留给程序员确切知道发生了什么的非常特定的情况。出于其他目的,更倾向于以人类可读的形式保存为文本文件。


推荐阅读