第五章 标准I/O库
来源:互联网 发布:上市公司网络投票规则 编辑:程序博客网 时间:2024/06/05 03:29
5.2 流和file对象
当用标准I/O库打开或创建一个文件时,我们已使一个流和一个文件相关联。
当一个流最初被创建时,它并没有定向。如若在未定向的流上使用个多字节I/o函数,则将该流的定向设置为宽定向的,若在未定向的流上使用一个单字节I/O函数,则将该流的定向设置为字节定向的。只有两个函数可改变流的定向。freopen清楚一个流的定向,fwide函数设置流的定向。
#include <stdio.h>
#include <wchar.h>
int fwide(FILE * fp ,int mode); 返回值:若流是宽定向的则返回正值, 若流是字节定向的则返回负值,或者若流是未定向的则返回0
根据mode参数的不同值,fwide函数执行不同的工作:
若mode参数值为负,fwide将试图使指定的流是字节定向的
若mode参数值为正,fwide将试图使指定的流是宽定向的
若mode参数值为0 ,fwide将不试图设置流的定向,但返回标识该流定向的值。
5.3 保准输入 标准输出 和标准出错
这三个标准I/O流通过预定义文件指针stdin,stdout 和stderr加以引用。这三个文件指针同样定义在头文件<stdio.h>中。
5.4 缓冲
标准I/O库提供缓冲的目的是尽可能减少使用read和writte调用次数.标准I/O提供了三种类型的缓冲:
(1)全缓冲.在填满标准I/O缓冲区后才进行实际I/O操作。对于驻留在磁盘上的文件通常是由标准I/O库实施全缓冲的。
(2)行缓冲。当在输入和输出中遇到换行符时,标准I/O库执行I/O操作。
(3)不带缓冲。标准I/O库不对字符进行缓冲存储。 标准出错流stderr通常是不带缓冲的,这就使得出错信息可以尽快显示出来,而不管它们是否含有一个换行符。
对任何一个给定的流, 如果我们并不喜欢这些系统默认的情况,则可调用下列两个函数中的一个更改缓冲类型:
#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值
可以使用setbuf函数打开或关闭缓冲机制。为了带缓冲进行I/O,参数buf必须指向一个长度为BUFSIZ的缓冲区(该常量定义在<stdio.h>中)。通常在此之后该流就是全缓冲的, 但是如果该流与一个终端设备相关,那么某些系统也可将其设置为行缓冲。为了关闭缓冲,将BUF设置为NULL。
使用setvbuf,我们可以精确的指定所需的缓冲类型。这里用mode参数实现的。
_IOFBF 全缓冲 _IOLBF行缓冲 _IONBF不带缓冲。
#include<stdio.h>
int fflush(FILE * fp); 成功返回0, 出错返回EOF
此函数使该流所有未写的数据都被传送至内核。作为一个特例,如若fp是NULL ,则此函数将导致所有输出流被冲洗。
5.5打开流
#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);
三个函数的返回值:若成功则返回文件指针, 若出错则返回NULL
fopen打开一个指定的文件。
freopen在一个指定的流上打开一个指定的文件,若该流已经打开,则先关闭该流。若该流已经定向,则freopen 清除该定向。
此函数一般用户将一个指定的文件打开为一个预定义的流:标准输入 标准输出或标准出错。
fdopen获取一个现有的文件描述符(我们可能从open ,dup ,dup2,fcntl ,pipe,socket socketpaire 或accept函数得到此文件描述符)并使一个标准的I/O流与该描述符相结合。
#include <stdio.h>
int fclose(FILE * fp); 返回值:若成功则返回0 , 若出错则返回EOF
在该文件被关闭之前,冲洗缓冲区中的输出数据。丢弃缓冲区中的任何输入数据。如果标准I/O库已经为该流自动分配了一个缓冲区,则释放此缓冲区。
当一个进程正常终止时(直接调用exit函数,或从main函数返回),则所有带写缓冲数据的标准I/O流都会被冲洗,所有打开的标准I/O流都会被关闭。
5.6 读和写
一旦打开了流,则可在三种不同类型的非格式化I/O中进行选择,对其进行读写操作:
1.每次一个字符的I/O。 一次读或写一个字符,如果流是带缓冲的,则标准I/O函数会被处理所有缓冲。
2.每次一行的I/O。 如果想要一次读或写一行,则使用fgets 和fputs.每行都以一个换行符终止。当调用fgets时,应该说能处理的最大行长。
3.直接I/O.fread和fwrite函数支持这种类型的I/O.每次I/O操作读或写某种数量的对象,而每个对象具有指定的长度。这两个函数常用于从二进制文件中每次读或写一个结构。
1.输入函数
以下三个函数可用于一次读一个字符。
#include <stdio.h>
int getc(FILE *fp);
int fgetc(FILE *fp);
int getchar(void);
//三个函数的返回值:若成功则返回下一个字符,若已到达文件结尾或出错则返回EOF。
getchar等价于getc(stdin).前两个函数的区别是 getc可被实现为宏,而fgetc则不能实现为宏。 这意味着:
(1)getc的参数不应该是具有副作用的表达式
(2)因为fgetc一定是一个函数,所以可以得到其地址。这就允许将fgetc的地址作为一个参数传递给另外一个函数。
不管是出错还是到达文件末尾,这三个函数都返回同样的值。为了区分这两种不同的情况,必须调用ferror或feof.
#include <stdio.h>
int ferror(FILE *fp);
int feof(FILE *fp ); //两个函数返回值:若条件为真则返回非0 真,否则返回0 假
void clearerr(FILE *fp);
在大多数实现中,为每个流在FILE对象中维持了两个标志 出错标志 文件结束标志 调用clearerr则清除这两个标志。
从流中读取数据后,可以调用ungetc将字符再压送回流中。
#include <stdio.h>
int ungetc(int c FILE *fp); //若成功 则返回0 若出错则返回EOF
注意:用ungetc压送回字符时,并没有将他们写到文件中或设备上,只是将它们写回标准I/O库的流缓冲区中。
2.输出函数
#include <stdio.h>
int putc(int c ,FILE *fp);
int fputc(int c , FILE *fp);
int putchar(int c); // 三个函数返回值:若成功则返回C 若出错则返回EOF
5.7每次一行I/O
下面两个函数提供每次输入一行的功能
#include<stdio.h>
char * fgets(char * restrict buf, int n ,FILE * restrict fp);
char * gets(char * buf); //两个函数返回值:若成功则返回buf,若已到达文件结尾或出错则返回NULL
说明:gets是一个不推荐使用的函数。会造成缓冲区溢出。
fputs 和 puts提供每次输出一行的功能.
#include<stdio.h>
int fputs(const char * restrict str, FILE * restrict fp);
int puts(const char * str); //两个函数返回值:若成功则返回非负值,若出错则返回EOF
函数fputs将一个以null符终止的字符串写到指定的流,尾端的终止符null补写出。
puts将一个以null符终止的字符串写到标准输出,终止符不写出。但是,puts然后又将一个换行符写到标准输出。
5.8 标准I/O的效率
一般而言 标准I/O和 无缓冲区I/O速度差不多, 无缓冲 要选择缓冲区的大小为blocksize,这样速度快一些。
5.9二进制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 prt,size_t size, size_t nobj, FILE * restrict fp); //两个函数的返回值:读或写的对象数
fread 和fwrite 返回读或写的对象数。对于读,如果出错或达到文件尾端,则此数字可以少于nobj.在这种情况下,应调用ferror或feof以判断究竟属于哪一种情况。对于写,如果返回值少于所要求的nobj,则出错。
5.10 定位流
有三种方法定位标准I/O流。
1.ftell和fseek函数,它们假定文件的位置可以存放在一个长整型中。
2.ftello和fseeko函数,可以使文件偏移量不必一定使用长整型。它们使用off_t数据类型代替了长整型。
3.fgetpos和fsetpos函数,他们使用一个抽象数据类型fpos_t记录文件的位置。这种数据类型可以定义为记录一个文件位置所需的长度。
5.11格式化I/O
1.格式化输出
printf,frpintf ,sprintf , snprintf
下列4中printf族的变体类似于上面的4种,但是可变参数表(...)代换成了arg
#include<stdarg.h>
#include<stdio.h>
int vprintf(const char * restrict format, va_list arg);
int vfprintf(FILE * restrict fp , const char * restrict format , va_list arg);
//两个函数的返回值:若成功则返回输出字符串, 若输出出错则返回负值
int vsprintf(char * restrict buf,const char * restrict format,va_list arg);
int vsnprintf(char * restrct buf, size_t n , const char * restrict format, va_list arg);
//两个函数的返回值:若成功则返回存入数组的字符数,若编码出错则返回负值
2.格式化输入
scanf, fscanf ,sscanf
变体的scanf类:
vscanf , vfscanf , vsscanf
5.12实现细节
每个标准I/O流都有一个与其相关联的文件描述符,可以对一个流调用fileno函数以获得其描述符
#include<stdio.h>
int fileno(FILE * fp); //返回值:与该流相关联的文件描述符
eg:
#include "apue.h"
void pr_stdio(const char *, FILE *);
int main(void)
{
FILE *fp;
fputs("enter any character\n", stdout);
if (getchar() == EOF)
err_sys("getchar error");
fputs("one line to standard error\n", stderr);
pr_stdio("stdin", stdin);
pr_stdio("stdout", stdout);
pr_stdio("stderr", stderr);
if ((fp = fopen("/etc/motd", "r")) == NULL)
err_sys("fopen error");
if (getc(fp) == EOF)
err_sys("getc error");
pr_stdio("/etc/motd", fp);
exit(0);
}
void pr_stdio(const char *name, FILE *fp)
{
printf("stream = %s, ", name);
/*
* The following is nonportable.
*/
if (fp->_IO_file_flags & _IO_UNBUFFERED)
printf("unbuffered");
else if (fp->_IO_file_flags & _IO_LINE_BUF)
printf("line buffered");
else /* if neither of above */
printf("fully buffered");
printf(", buffer size = %d\n", fp->_IO_buf_end - fp->_IO_buf_base);
}
5.13 临时文件
#include<stdio.h>
char * tmpnam(char * ptr); //返回值:指向唯一路径名的指针
FILE * tmpfile(void ); //返回值:若成功则返回文件指针,若出错则返回NULL
若ptr是NULL,则所产生的路径名存放在一个静态区中,指向该静态区的指针作为函数值返回。下一次调用tmpname时,会重写该静态区。 若ptr不是NULL,则认为它指向长度至少是L_tmpname个字符的数组。 L_tmpname定义在头文件<stdio.h>中
注:tempnam是tmpnam的一个变体,允许加前缀
5.14标准I/O的替代软件
标准I/O库的一个不足之处是效率不高,这与它需要复制的数据量有关。当使用每次一行函数fgets和fputs时,通常需要复制两次数据:一次是在内核和标准I/O缓冲之间。第二次是在标准I/O缓冲区和用户程序中的行缓冲区之间。
- 第五章 标准I/O库
- apue 第五章 标准i/o库
- 第五章 标准I/O库
- 第五章标准I/O库
- 第五章 标准I/O库
- 第五章 标准I/O库
- UNP第五章 标准I/O库
- AUPE学习第五章------标准I/O库
- APUE学习: 第五章, 标准I/O库
- APUE读书笔记-第五章 标准I/O库
- 《APUE》笔记-第五章-标准I/O库
- APUE-第五章学习-标准I/O库-习题
- 第五章 标准I/O库 课后练习题
- 第五章 文件I/O、高级I/O、标准I/O、mmap映射
- apue学习笔记(第五章 标准I/O)
- apue学习第九天——标准I/O库(第五章)
- APUE学习笔记3——第五章——标准I/O库
- UNIX环境高级编程——第五章-标准I/O库
- 应用层协议分析-HTTP
- 第一章 UNIX基础知识
- 第三章 文件 I/O
- 表设计的原则与方法分析:追求表价值的最大化
- 第四章 文件和目录
- 第五章 标准I/O库
- Minifilter的动态安装、加载及卸载
- 第六章 系统数据文件和信息
- 第七章 进程环境
- 第8章 进程控制
- 第10章 信号
- JS专题1:基本概念
- JS专题2:变量 作用域和内存问题
- [.Net码农](转)图解WPF程序打包全过程