本章描述I/O库 : 标准I/O库处理很多细节 : 如缓冲区分配 ,以优化块长度执行I/O等 .
这些处理使用户不必担心如何选择正确的块长度 ,但不深入理解I/O库函数的操作 ,也会带来一些问题 .
流和FILE对象 : 所有 [I/O函数] 都是围绕 [文件描述符] 的 ,当打开一个文件时 ,即返回一个文件描述符 ,然后该文件描述符就用于后续的I/O操作 .
而对于 [标准I/O库] ,它们的操作是围绕 [流] 进行的,当用标准I/O库打开或创建一个文件时,我们已使用一个流与文件相关联.
流的定向 : 决定了所读写的字符是单字节还是多字节的 .当一个流最初被创建时 ,它并没有定向 .
freopen函数 ,清除一个流的定向 ;
fwide函数可用于设置流的定向 ;
标准I/O函数fopen返回一个纸箱 FILE对象的指针 ,该对象通常是一个结构 ,它包含了标准I/O库为管理该流需要的所有信息 ,
包括用于实际I/O的 :文件描述符 :指向该流缓冲区的指针 :缓冲区长度 :当前在缓冲区中的字节数 :及出错标志等 .
对一个进程预定义了3个流 ,并且这三个流可以自动的被进程使用 ,它们是是 :标准输入 ,输出 ,错误 .
引用的文件描述符即 :STDIN_FILENO : STDOUT_FILENO : STDERR_FILENO.
这三个标准流通过预定义指针 : stdin,stdout,stderr 引用包含在<stdio.h>中。
5.4缓冲 : 标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数 ,
它也对每个I/O流自动的进行缓冲管理 ,避免了应用程序需要考虑这一点所带来的麻烦。
标准I/O提供了三种类型的缓冲:
1.全缓冲 : 在填满标准I/O缓冲区后才进行实际I/O操作 .
2.行缓冲 : 当在输入和输出遇到换行符时 ,标准I/O库执行I/O操作 ( 当涉及到一个终端时通常使用行缓冲 ).
3.不带缓冲 : 标准I/O库不对字符进行缓冲存储。
5.5打开流 : fopen , freopen , fdopen .
5.6读和写流 : getc fgetc , getchar.
5.7每次一行I/O fgets gets
5.8标准I/O效率
5.10定位流
例程 :
/*******************************************************
*对三个标准IO打印缓冲信息
********************************************************/
#include <apue.h>
#include <myerr.h>
/********************************************************
*
*FILE 结构体
*
struct _iobuf {
char *_ptr; //文件输入的下一个位置
int _cnt; //当前缓冲区的相对位置
char *_base; //指基础位置(应该是文件的其始位置)
int _flag; //文件标志
int _file; //文件的有效性验证
int _charbuf; //检查缓冲区状况,如果无缓冲区则不读取
int _bufsiz; //文件的大小
char *_tmpfname; //临时文件名
};
typedef struct _iobuf FILE;
*********************************************************/
void pr_stdio(const char *,FILE *);
int is_unbufed(FILE *); //不带缓冲
int is_linebufed(FILE *); //行缓冲
int buf_size(FILE *); //全缓冲
int main()
{
FILE *fp;
fputs("Enter Any Character\n",stdout);
if(getchar()==EOF) err_sys("getchar error");
fputs("One Line to STDERR\n",stderr);
pr_stdio("stdin",stdin);
pr_stdio("stdout",stdout);
pr_stdio("stderr",stderr);
if((fp=fopen("/etc/passwd","r"))==NULL) err_sys("fopen error");
if(getc(fp)==EOF) err_sys("getc error");
pr_stdio("/etc/passwd", fp);
return 0;
}
/*************************************************
,打印缓冲信息
标准IO 都是行缓冲 bufsize = 1024
1024 是缓冲区长度 ,并不是讲输入输出行 限制为 1024 字节
每1024字节 系统调用一次write 。
标准错误 是 不带缓冲 bufsize = 1
普通文件 全缓冲 其缓冲长度是该文件系统优先选用的IO长度
(从stat结构中 得到 st_blksize 值) (此处4096)
*************************************************/
void pr_stdio(const char * name,FILE * fp)
{
printf("stream =%s, ", name);
if(is_unbufed(fp)) printf("unbufed\n");
else if(is_linebufed(fp)) printf("line buffered\n");
else printf("fully buffererd\n");
//printf(", buffer size =%d\n",buffer_size(fp));
}
int is_unbufed(FILE * fp)
{
return (fp->_flags & _IO_UNBUFFERED);
}
int is_linebufed(FILE *fp)
{
return (fp->_flags & _IO_LINE_BUF);
}
/*
int buf_size(FILE *fp)
{
return (fp->_bf._size);
}
*/