在文件I/O中所有函数都是针对文件描述符的,对于标致I/O库,他们的操作则是围绕流进行的。当用标准I/O库打开或创建一个文件时,我们已使一个流与一个文件相关联。
当打开一个流时,标准I/O函数fopen返回一个指向FILE对象的指针。该对象通常是一个结构,它包含了标准I/O库为管理该流所需要的所有信息,包括:用于实际I/O的文件描述符、指向用于该流缓冲区的指针、缓冲区的长度、当前在缓冲区中的字符数以及出错标志等等。
在文件I/O中已经介绍标准I/O是提供缓冲区的。标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数。标准I/O库处理很多细节,例如缓冲区分配,以优化长度执行I/O等。
标准I/O提供了三种类型的缓冲:
1)全缓冲。这种情况下,在填满标准I/O缓冲区后才进行实际I/O操作。对于驻留在磁盘上的文件通常是由标准I/O库实施全缓冲的。在一个流上执行第一次I/O操作时,相关标准I/O函数通常调用malloc获得需使用的缓冲区。
2)行缓冲。在这种情况下,当在输入和输出中遇到换行符是,标准I/O库执行I/O操作。这允许我们一次输出一个字符(标准I/Ofputc函数),但只有在写了一行之后才进行实际I/O操作。当流涉及一个终端时(例如标准输入和标准输出),通常使用行缓冲。
对于行缓冲有两个限制。第一,因为标准I/O库用来收集每一行的缓冲区的长度是固定的、所以只要填满了缓冲区,那么即使还没有写一个换行符,也进行I/O操作。第二,任何时候只要通过标准I/O库要求从(a)一个不带缓冲的流,或者(b)一个行缓冲的流(它要求从内核得到数据)得到输入数据,那么就会造成冲洗所有行缓冲输出流。
3)不带缓冲。标准I/O库不对字符进行缓冲存储。例如,如果用标准I/O函数fputs写15个字符到不带缓冲的流中,则该函数很可能用上面讲述的write系统调用函数将这些字符立即写至关联的打开的文件上。
对于一个给定的流,我们可以通过下面的函数更改缓冲类型:
#include <stdio.h>
void setbuf(FILE *restrict fp,char *restrict buf);
int setvbuf(FILE *restrict fp,char *restrict buf,int mode,size_t size); // 若成功则返回0,出错则返回非0值
mode参数设置:
_IOFBF 全缓冲
_IOLBF 行缓冲
_IONBF 不带缓冲
在任何时候都可以强制冲洗一个流。
#include <stdio.h>
int fflush(FILE *fp);
此函数使该流所有未写的数据都被传送至内核。
打开流的函数:
#include <stdio.h>
FILE *fopen(const char *restrict pathname,const char *restrict type);
FILE *freopen(const char *restrict pathname,const char *restrict type,FILE *restrict fp);
FILE *fdopen(int filedes,const char *type);
1)fopen打开一个指定的文件
2)freopen在一个指定的流上打开一个指定的文件,如若该流已经打开,则关闭该流。
3)fdopen获取一个现有的文件描述符,并使一个标准的I/O流与该描述符相结合。
函数中的参数type的取值;
Type |
说明 |
r/rb |
为读而打开 |
w/wb |
把文件截短至0,或为写而创建 |
a/ab |
添加:为在文件末尾写而打开,或为写而创建 |
r+/r+b/rb+ |
为读和写打开 |
w+/w+b/wb+ |
把文件截短至0,或为读和写打开 |
一旦打开了流,则可在三张不同类型的非格式花I/O中进行选择,对其进行读、写操作:
1)每次一个字符的I/O。一次读或写一个字符,如果流时带缓冲的,则标准I/O函数会处理所有缓冲。
2)每次一行的I/O。如果想要一次读或写一行,则使用fgets和fputs.
3)直接I/O。fread和fwrite函数支持这种类型的I/O。每次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);
这两个函数可以读写对象、结构数组,使用二进制I/O的基本问题是,它只能用于读在同一系统上已写的数据。因为在一个结构中,同一成员的偏移量可能因编译器和系统而异。用来存储多字节整数和浮点数值的二进制格式在不同的机器体系结构间可能不同。