对于操作系统而言,I/O操作可以分为两类,一类是带缓存的IO,又称为标准IO(C标准库中提供了标准IO库,即stdio),它实现了跨平台的用户缓存解决方案。另一类是Unix/Linux下的文件IO,又称直接IO,即文件访问机制不经过操作系统内核的缓存,数据直接在磁盘和应用程序地址空间进行传输。
标准IO在系统调用的上一层多加了一个缓冲区,也因此引入了流的概念,在UNIX/Linux下表示为FILE*(并不限于UNIX/Linux,ANSI C都有FILE的概念)。我们可以先看一下FILE结构体。
标准IO提供了三种类型的缓冲:
1.
2. 通过系统IO读写文件时,每次操作都会执行相关系统调用。这样处理的好处是直接读写实际文件,坏处是频繁的系统调用会增加系统开销。标准IO可以看成是文件IO的基础上封装了缓冲机制。从而减少了系统调用的次数。
①普通文件(标准IO)
数据不需要立刻更新,只需要最后写入文件即可。
②设备/网络(文件IO)
数据往往需要实时更新
比如,显卡缓冲区,修改以后要立即在屏幕上进行显示
比如,网络中传送数据,需要发送给对方
1、 打开文件:fopen与open
1) 标准IO使用fopen打开文件:FILE *fp= fopen(const char* path,const char* mode);其中path是文件名,mode用于指定文件打开的模式的字符串。如果成功打开,返回一个FILE文件指针,如果失败返回NULL。这里的文件指针并不是指向实际的文件,而是一个关于文件信息的数据包,其中包括文件使用的缓存信息。
mode的字符串形态:
r:以只读方式打开文件,该文件必须存在
r+:以读/写方式打开文件,该文件必须存在
w:打开只写文件,若文件存在则文件长度清为0,即该文件内容消失,若不存在则创建该文件
w+:打开可读/可写文件,若文件存在则文件长度清0,即该文件内容消失,若文件不存在则创建该文件
a:以附加的方式打开只写文件。若文件不存在,则会创建该文件,若文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留(EOF符保留)
a+:以附加的方式打开可读/可写文件。若文件不存在,则会创建该文件,若文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留(EOF符不保留)
上述的形态字符串都可以再加一个b字符,如rb、w+b或ab+等组合,加入b字符用来告诉函数库以二进制模式打开文件。如果不加b,表示默认加了t,即rt、wt,其中t表示以文本模式打开文件。
EOF符:表示文件结束符(end of file)。在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。在文本文件中,数据都是以字符的ASCII代码值的形式存放,而ASCII代码值的范围是0~127,不可能出现-1,因此可以用EOF作为文件结束标志。实际上EOF的值通常为-1,但他依系统有所不同。很多文件处理函数错误后的返回值也是EOF,因此常被用来判断调用一个函数是否成功。
2) 系统IO使用open函数打开一个文件:int open(const char pathname,int flags,.../*mode_t mode */);与fopen类似,name表示文件名字符串,而flags指定打开的模式。成功返回一个正整数成为文件描述符,这与标准IO显著不同,失败的话返回-1,与标准IO返回NULL也是不同的。
flags的必选形态:
O_RDONLY(只读)
O_WRONLY(只写)
O_RDWR(可读可写)
可选形态:
O_APPEND 每次写操作都写入文件
O_CREAT 如果指定文件不存在,则创建这个文件
O_EXCL 如果要创建的文件已存在,则返回 -1,并且修改 errno 的值
O_TRUNC 如果文件存在,并且以只写/读写方式打开,则清空文件全部内容
O_NOCTTY 如果路径名指向终端设备,不要把这个设备用作控制终端。
O_NONBLOCK 如果路径名指向 FIFO/块文件/字符文件,则把文件的打开和后继 I/O设置为非阻塞模式(nonblocking mode)
参数三:第三个参数有第二个参数确定是否需要仅当创建文件时使用
eg:open(pathname,O_RDONLY|O_CREAT ,0664);
2、 关闭文件:fclose和close
打开文件与关闭文件一般成对存在,这样做的目的是为了防止没有关闭文件而造成数据流失。
1) 标准IO使用fclose关闭文件,与打开文件是相对的。将文件指针传入即可,如果成功关闭,返回0,否则返回EOF。
2) 系统IO使用close关闭文件,与fclose类似,只不过当错误发生时返回的是-1,而不是EOF,成功关闭同样是返回0。