如果进行二进制I/O操作,那么我们更愿意一次读或写整个结构。因此,提供了下列两个函数以执行二进制I/O操作。

#include <stdio.h>
size_t fread( void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp );
size_t fwrite( const void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp );
两个函数的返回值:读或写的对象数

这些函数有两种常见的用法:

(1)读或写一个二进制数组。例如,为了将一个浮点数组的第2-5个元素写至一个文件上,可以编写如下程序:

float    data[];

if( fwrite( &data[], sizeof(float), , fp ) !=  )
err_sys("fwrite error" );

其中,指定size为每个数组元素的长度,nobj为欲写的元素数。

(2)读或写一个结构。例如,可以编写如下程序:

struct {
short count;
long total;
char name[NAMESIZE];
} item; if( fwrite( &item, sizeof(item), , fp ) != )
err_sys( "fwrite error" );

其中,指定size为结构的长度,nobj为1(要写的对象数)。

将这两个例子结合起来就可读或写一个结构数组。为了做到这一点,size应当是该结构的sizeof,nobj应是该数组中的元素个数。

fread和fwrite返回读或写的对象数。对于读,如果出错或到达文件尾端,则此数字可以少于nobj。在这种情况下,应调用ferror或feof以判断究竟属于哪一种情况。对于写,如果返回值少于所要求的nobj,则出错。

使用二进制I/O的基本问题是,它只能用于读在同一系统上已写的数据。多年之前,这并无问题(那时,所有的UNIX系统都运行于PDP-11上),而现在,很多异构系统通过网络相互连接起来,而且,这种情况已经非常普遍。常常有这种情形,在一个系统上写的数据,要在另一个系统上进行处理。在这种环境下,这两个函数可能就不能正常工作,其原因是:

(1)在一个结构中,同一成员的偏移量可能因编译器和系统而异(由于不同的对准要求)。确实,某些编译器有一个选项,选择它的不同值,或者使结构中的各成员紧密包装(这可以节省存储空间,而运行性能则可能有所下降);或者准确对齐(以便在运行时易于访问结构中的各成员)。这意味着即使在同一个系统上,一个结构的二进制存放方式也可能因编译器选项的不同而不同。

(2)用来存储多字节整数和浮点值的二进制格式在不同的机器体系结构间也可能不同。

在不同系统之间交换二进制数据的实际解决方法是使用较高级的协议(例如网络协议)。

本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

标准I/O库之二进制I/O的更多相关文章

  1. 标准I/O库之读和写流

    一旦打开了流,则可在三种不同类型的非格式化I/O中进行选择,对其进行读.写操作: (1)每次一个字符的I/O.一次读或写一个字符,如果流是带缓冲的,则标准I/O会处理所有缓冲. (2)每次一行的I/O ...

  2. UNIX环境高级编程---标准I/O库

    前言:我想大家学习C语言接触过的第一个函数应该是printf,但是我们真正理解它了吗?最近看Linux以及网络编程这块,我觉得I/O这块很难理解.以前从来没认识到Unix I/O和C标准库I/O函数压 ...

  3. UNIX环境高级编程——标准I/O库

    对一个进程预定义了三个流,并且这三个流可以自动的被进程使用,它们是:标准输入.标准输出.和标准错误. 标准I/O库提供缓冲的目的是尽可能减少使用read和write的次数. 标准I/O库提供了三种类型 ...

  4. APUE(5)---标准I/O库 (3)

    十.定位流 #include <stdio.h> long ftell(FILE *fp); //若成功,返回当前文件位置指示:若出错,返回-1L int fseek(FILE *fp, ...

  5. UNIX高级环境编程(7)标准IO函数库 - 二进制文件IO,流定位,创建临时文件和内存流

    1 二进制IO(Binary IO) 在前一篇我们了解了逐字符读写和逐行读写函数. 如果我们在读写二进制文件,希望以此读写整个文件内容,这两个函数虽然可以实现,但是明显会很麻烦且多次循环明显效率很低. ...

  6. UNIX环境高级编程 第5章 标准I/O库

    本章是关于C语言标准I/O库的,之所以在UNIX类系统的编程中会介绍C语言标准库,主要是因为UNIX和C之间具有密不可分的关系.由于UNIX系统存在很多实现,而每个实现都有自己的标准I/O库,为了统一 ...

  7. Unix环境高级编程(三)标准I/O库

    标准I/O库是ISO C的标准,在很多操作系统上面都实现.Unix文件I/O函数都是针对文件描述符的,当打开一个文件的时候,返回该文件描述符用于后续的I/O操作.而对于标准I/O库,操作则是围绕流进行 ...

  8. 标准I/O库

    前言:我想大家学习C语言接触过的第一个函数应该是printf,但是我们真正理解它了吗?最近看Linux以及网络编程这块,我觉得I/O这块很难理解.以前从来没认识到Unix I/O和C标准库I/O函数压 ...

  9. APUE(5)---标准I/O库 (2)

    六.读和写流 一旦打开了流,则可在3种不同类型的非格式化I/O中进行选择,对其进行读.写操作:1)每次一个字符的I/O,一次读或写一个字符,如果刘时代缓冲的,则标准I/O函数处理所有缓冲:2)每次一行 ...

随机推荐

  1. VC常用数据类型使用转换

    我们先定义一些常见类型变量借以说明 int i = 100; long l = 2001; float f=300.2; double d=12345.119; char username[]=&qu ...

  2. Android 使控件各占屏幕的一半

    在xml中将两个要占屏幕一半的控件都加上android:layout_weight="1": 注意:weight只能用在LinearLayout布局中. 在LinearLayout ...

  3. html5 动画精灵

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...

  4. c#调用c++动态库的一些理解

    调用c++动态库一般我们这样写   [DllImport("UCamer.dll", CallingConvention = CallingConvention.Winapi)] ...

  5. 加快VisualStudio的开发速度--VS的一些开发技巧

    最近不得不使用VisualStudio来进行一些开发,用习惯了Eclipse,感觉VS很难上手,不过通过google,把VS进行Eclipse化,顺便记录下来,以防忘记. 1)显示文字的自动完成. 改 ...

  6. RegisterFunction z

    #region SolidWorks Registration [ComRegisterFunctionAttribute] public static void RegisterFunction(T ...

  7. Selenium WebDriver + Grid2 + RSpec之旅(四) ----通过RSpec编写测试用例

    Selenium WebDriver + Grid2 + RSpec之旅(四) ----通过RSpec编写测试用例 自动化测试和手工测试一样,是要有测试用例,有检查点和测试结果的,接下来我们通过RSp ...

  8. MFC之RTTI与动态创建

    本人能力.精力有限,所言所感都基于自身的实践和有限的阅读.查阅,如有错误,欢迎拍砖,敬请赐教——博客园:钱智慧. 在说RTTI之前需要明白c++中类静态成员的初始化特点:类的静态数据成员需要在类体外显 ...

  9. 【HTML】Beginner1:TagsAttributesElements

    HTML(Hypertext Text Mark-up Language)&(How To Make L) HTML is used for meaning and CSS is used f ...

  10. Html笔记(七)表单

    表单标签: <form> 表单标签是最常用的标签,用于与服务器端的交互. <input>:输入标签:接受用户输入信息 其中type属性指定输入标签的类型 文本框 text:输入 ...