Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1426337
  • 博文数量: 842
  • 博客积分: 12411
  • 博客等级: 上将
  • 技术积分: 5772
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-14 14:43
文章分类

全部博文(842)

文章存档

2013年(157)

2012年(685)

分类: 系统运维

2012-05-14 17:18:20



5.6节的函数一次操作一个字符,而5.7节的函数一次操作一行。如果我们执行二进制I/O,我们经常是想一次读写整个结构。为了使用getc或 putc,我们必须在整个结构里循环,一次一个字节,读写各个字节。我们不能使用一次一行函数,因为fputs当碰到空字节时结束写,而在结构里可能会有 空字节。类似的,fgets不能用来输入如果任何数据字节包含空字节或的换行符。因此,以下两个函数被用来执行二进制I/O。



  1. #include <stdio.h>

  2. size_t fread(void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp);

  3. size_t fwrite(const void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp);

  4. 两者都返回读或写的对象数。


这些函数有两种普遍的使用方法:

1、读写一个二进制数组。例如,写一个浮点数组的第2到第5人元素,我们可以写:
float data[10];
if (fwrite(&data[2], sizeof(float), 4, fp) != 4)
    err_sys("fwrite error");

这里,我们指定size作为数组每个元素的尺寸而nobj作为元素的数量。


2、读写一个结构体。例如,我们可能这样写:


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


这里,我们指定size作为结构体的尺寸而nobj指定为1(写的对象的数量)。


这两种情况的明显的扩展是读写一个结构体数组。要这样做,size应该是结构体的sizeof,而nboj应该是数组的元素数量。


fread和fwrite都返回读入或写出的对象的数据。对于read,这个数量可以比nboj小,如果有错误发生或碰到文件结束。这些种情况下ferror和feof必须调用。对于write,如果返回值比所需的nobj少,表示发生错误。


二进制I/O的一个基本问题,是它只能用来读在同一系统上写的数据。这在很多年前,当所有UNIX系统都在PDP-11上时,是没问题的。但如今多种多样 的系统用网络连接在一起。想要在一个系统上写数据而在另一个上处理它是很普遍的。这两个函数将不能工作,基于两个原因:


1、一个结构体里的成员的偏移量在编译器间和系统间可以不同,因为不同的对齐需要。事实上,一些编译器有一个选项允许结构体被紧凑打包,以运行时的性能为 代价节省空间,或者精确地排列,来优化每个成员的运行访问时间。这意味着即使在同一个系统上,一个结构体的字节排列也可以不同,取决于编译器选项。


2、用来存储多字节整型和浮点型的值在各种机器架构上不同。


我们将在16章讨论套接字时碰到一些这样的问题。在不同系统上交换二进制数据的真实解决方案,是使用更高层的协议。我们将在8.14节回到fread函数,当我们用它来讯一个二进制结构体,UNIX进程记账记录的时候。


阅读(267) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~