系统调用IO和标准IO(2)

对于一个打开的流,可以调用setbuf或setvbuf改变其缓冲类型.

//成功返回0,失败返回非0 void setbuf(FILE *fp, char *buf); int setvbuf(FILE *fp, char *buf, int mode, size_t size);

setbuf用于关闭或打开fp的缓冲机制,若打开,则buf必须指向一个长度为BUFSIZ的缓冲区;若关闭,则buf设为NULL

setvbuf通过参数mode可精确设置缓冲类型,_IOLBF==全缓冲, _IOLBF==行缓冲,_IONBF==无缓冲

当setvbuf设置为带缓冲时,buf必须指向一个长度为size的缓冲区,推荐将buf设为NULL让系统自动分配缓冲区长度,此时size可设为0

对于全缓冲和行缓冲,不管是否满足IO条件,都可以使用fflush函数强制进行IO操作,我们称其为冲洗。

//成功返回0,失败返回EOF //若fp为NULL,将导致冲洗所有输出流 int fflush(FILE *fp); 常用标准IO函数

常用的标准IO函数分为以下几大类:

打开和关闭流

定位流

读写流,包括文本IO、二进制IO和格式化IO三种

打开和关闭流 //成功返回文件指针,失败返回NULL FILE *fopen(const char *pathname, const char *type); //成功返回0,失败返回EOF void fclose(FILE *fp);

fopen打开由pathname指定的文件,type指定读写方式:

使用字符b作为type的一部分,使得标准IO可以区分文本文件和二进制文件

Linux内核不区分文本和二进制文件,因此在Linux系统下使用字符b实际上没有作用,只读、只写、读写分别指定为"r"、"w"、"rw"即可

Windows中,文本文件只读、只写、读写分别为"r"、"w"、"rw",二进制文件只读、只写、读写分别为"rb"、"wb"、"rb+"

只读方式要求文件必须存在,只写或读写方式会在文件不存在时创建

系统调用IO和标准IO

fclose关闭文件,关闭前缓冲区中的输出数据会被冲洗,输出数据则丢弃。

定位流

流的定位类似于系统调用IO中获取当前文件偏移量,ftell和fseek函数可用于定位流。

//成功返当前文件位置,出错返回-1 int ftell(FILE *fp); //成功返回0,失败返回-1 void fseek(FILE *fp, long offset, int whence);

offset和whence含义及可设的值与系统调用IO中的lseek相同,不再赘述,但如果是在非Linux系统,则有一点需要注意:

对于二进制文件,文件位置严格按照字节偏移量计算,但对于文本文件可能并非如此

定位文本文件时,whence必须是SEEK_SET,且offset只能是0或ftell返回值

文本IO

文本IO有两种:

每次读写一个字符

每次读写一行字符串

/* * 每次读写一个字符 */ //成功返回下一个字符,到达文件尾或失败返回EOF int getc(FILE *fp); //可能实现为宏,因此不允许将其地址作为参数传给另一个函数,因为宏没有地址 int fgetc(FILE *fp); //一定是函数 int getchar(); //等价于getc(stdin) //成功返回c,失败返回EOF int putc(int c, FILE *fp); //可能实现为宏,因此不允许将其地址作为参数传给另一个函数,因为宏没有地址 int fputc(int c, FILE *fp); //一定是函数 int putchar(int c); //等价于putc(c, stdout) /* * 每次读写一行字符串 */ //成功返回str,到达文件尾或失败返回EOF char *fgets(char *str, int n, FILE *fp); //从fp读取直到换行符(换行符也读入),str必须以'\0'结尾,故包括换行符在内不能超过n-1个字符 //成功返回非负值,失败返回EOF int fputs(const char *str, FILE *fp); //将字符串str输出到fp,str只要求以'\0'结尾,不一定含有换行符 二进制IO

二进制IO就是fread和fwrite。

//返回读或写的对象数 size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp); size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp);

二进制IO常见的用法包括:

读写一个二进制数组

读写一个结构

上述两种用法结合起来,还可以实现读写一个结构数组。

struct Item { int id; char text[100]; }; int data[10]; struct Item item; struct Item item[10]; //读写二进制数组 fread(&data[2], sizeof(int), 4, fp); fwrite(&data[2], sizeof(int), 4, fp); //读写结构 fread(&item, sizeof(item), 1, fp); fwrite(&item, sizeof(item), 1, fp); //读写结构数组 fread(&item, sizeof(item[0]), sizeof(item) / sizeof(item[0]), fp); fwrite(&item, sizeof(item[0]), sizeof(item) / sizeof(item[0]), fp); 格式化IO

格式化IO包括输入函数族和输出函数族,我们剔除了不常用的与文件指针fp、文件描述符fd相关的API,仅保留常用的3个输出函数和2个输入函数。

//成功返回输出或存入buf的字符数(不含'\0'),失败返回负值 int printf(const char *format, ...); int sprintf(char *buf, const char *format, ...); int snprintf(char *buf, size_t n, const char *format, ...);

sprintf和snprintf会自动在buf末尾添加字符串结束符'\0',但该字符不包括在返回值中

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/79cb31e592fdaa5b339c22432b78ce06.html