APUE学习笔记 第五章 标准I/O库


第五章 标准I/O

1流和FILE对象

对于标准I/O库,它们的操作是围绕流进行的。流的定向决定了所读、写的字符是单字节还是多字节的。

#include <stdio.h>
#include <wchar.h>
int fwide(FILE *fp,int mode);
//返回值:若流是宽定向的,返回正值;若流是字节定向的,返回负值;若流是未定向的,返回0.

fwide函数可用于流的定向。根据mode参数的不同值,fwide函数执行不同的工作。

若mode参数值为负,fwide将试图使指定的流是字节定向的

若mode参数值为正,fwide将试图使指定的流是宽定向的

若mode参数值是0,fwide将不试图设置流的定向,但返回标志该流定向的值

当一个流最初被创建时,它并没有定向。若在未定向的流上使用一个多字节(单字节)I/O函数,则将该流设置为宽(字节)定向。fwide并不改变已定向流的定向。

 

2标准输入、标准输出和标准错误

对一个进程预定义了3个流:stdinstdoutstderr。这些流引用的文件与文件描述符STDIN_FILENOSTDOUT_FILENOSTDERR_FILENO所引用的相同。

 

3、缓冲

标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数,标准I/O提供了以下3种类型的缓冲:

a、全缓冲,在这种情况下,在填满标准I/O缓冲区后才进行实际I/O操作。如磁盘上的文件通常实施全缓冲。

b、行缓冲,在这种情况下,当在输入和输出中遇到换行符,标准I/O执行I/O操作。如标准输入输出。

c、不带缓冲,标准I/O库不对字符进行缓冲存储。标准错误流stderr通常是不带缓冲的。

我们可以调用下面两个函数更改缓冲类型

#include <stdio.h>
void setbuf(FILE *restrict fp,char *restrict buf);
int setvbuf(FILE *restrict fp,char *buf,int mode,size_t size);
//返回值:若成功,返回0;若出错,返回非0.

可以使用setbuf打开或关闭缓冲机制,参数buf指定一个长度为BUFSIZ的缓冲区。将buf设置为NULL可以关闭缓冲。

使用setvbuf,我们可以精确地说明所需的缓冲类型。这是用mode参数实现的:

_IOFBF 全缓冲

_IOLBF 行缓冲

_IONBF 不带缓冲

我们可以通过fflush函数冲洗一个流,此函数使该流所有未写的数据都被传送至内核。

#include <stdio.h>
int fflush(FILE *fp);
//返回值:若成功,返回0;若出错,返回EOF。

 

4、打开流

下面3个函数打开一个标准I/O流

#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 fd,const char *type);
//返回值:若成功,返回文件指针;若出错,返回NULL。

    这三个函数的区别如下:

(1)、fopen函数打开路径名为pathname的一个指定的文件;

(2)、freopen函数在一个指定的流上打开一个指定的文件,如若该流已经打开,则先关闭该流。若该流已经定向,则使用freopen清除该定向。此函数一般用于将一个指定的文件打开为一个预定义的流:标准输入、标准输出或标准错误。

(3)、fdopen函数取一个已有的文件描述符,并使一个标准的I/O流与该描述符相结合。此函数常用于由创建管道和网络通信通道函数返回的描述符,因为这些特殊类型的文件不能用标准I/O函数fopen打开。

type参数指定对该I/O流的读、写方式,ISO C规定type参数可以有如下15种不同的值:

其中b作为type的一部分,这使得标准I/O系统可以区分文本文件和二进制文件。

调用fclose关闭一个打开的流

#include <stdio.h>
int fclose(FILE *fp);
//返回值:若成功,返回0;若出错,返回EOF。

    在该文件被关闭之前,冲洗缓冲中的输出数据。缓冲区中的任何输入数据被丢弃。如果标准I/O库已经为该流自动分配了一个缓冲区,则释放该缓冲区。当一个进程正常终止时,则所有带未写缓冲数据的标准I/O流都被冲洗,所有打开的标准I/O流都被关闭。

 

5、读写流

以下3个函数可用于一次读一个字符

#include <stdio.h>
int getc(FILE *fp);
int fgetc(FILE *fp);
int getchar(void);   //等同于getc(stdin)
//返回值:若成功,返回下一个字符;若已到达文件尾端或出错,返回EOF。

对应上面所述的每个输入函数都有一个输出函数

#include <stdio.h>
int putc(int c,FILE *fp);
int fputc(int c,FILE *fp);
int putchar(int c);
//返回值:若成功,返回c;若出错,返回EOF。

    不管是出错还是到达文件尾端,三个输入函数都返回同样的值,可以用下面的函数区分:

#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);
返回值:若成功,返回c;若出错,返回EOF。

 

6、每次一行I/O

下面两个函数提供每次输入一行的功能

#include <stdio.h>
char *fgets(char *restrict buf,int n,FILE *restrict fp);  //buf为缓冲区地址,读入的行将送入其中,参数n指定缓冲的长度
char *gets(char *buf);  //从标准输入读,不推荐使用
//返回值:若成功,返回buf;若已到达文件尾端或出错,返回NULL。

 fputs和puts提供每次输出一行的功能

#include <stdio.h>
int fputs(const char *restrict str,FILE *restrict fp);
int puts(const char *str);
//返回值:若成功,返回非负值;若出错,返回EOF。

函数fputs将一个以null字节终止的字符串写到指定的流,而puts写到标准输出。

 

7二进制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);

参数size为欲写结构的长度,nobj为欲写的元素个数,函数返回的是读或写的对象数。这些函数有以下两种常见的用法

//(1)、读或写一个二进制数组:
float data[10];
if(fwrite(&data[2],sizeof(float),4,fp)!=4)
    err_sys("fwrite error");
//(2)、读写一个结构
struct{
      short count;
      long total;
      char name[NAMESIZE];  
}item;

if(fwrite(&item,sizeof(item),1,fp)!=1)
     err_sys("fwrite error");

8、定位流

有3种方法定位标准I/O流

#include <stdio.h>
long ftell(FILE *fp);   
返回值:若成功,则返回当前文件位置指示,出错则返回-lL
int fseek(FILE *fp,long offset,int whence);
返回值:若成功,返回0;若出错,返回-1;
void rewind(FILE *fp);

除了偏移量的类型是off_t而非long以外,ftello函数与ftell相同,fseeko函数与fseek相同

#include <stdio.h>
off_t ftello(FILE *fp);
int fseeko(FILE *fp,off_t offset,int whence);

下面函数是ISO C标准引入的

#include <stdio.h>
int fgetpos(FILE *restrict fp,fpos_t *restrict pos);
int fsetpos(FILE *fp,const fpos_t *pos);
返回值:若成功,返回0;若出错,返回非0.

    fgetpos将文件位置指示器的当前值存入由pos指向的对象中,在以后调用fsetpos时,可以使用此值将流重新定位至该位置。

 

9、格式化I/O

    格式化输出是由printf函数处理的

#include <stdio.h>
int printf(const char *restrict format,...);
int fprintf(FILE *restrict fp,const char *restrict format,...);
int dprintf(int fd,const char *restrict format,...);
  //三个函数返回值:若成功,返回输出字节数;若出错,返回负值
int sprintf(char *restrict buf,const char *restrict format,...);
  //返回值:若成功,返回存入数组的字符数;若出错,返回负值。
int snprintf(char *restrict buf,size_t n,const char *restrict format,...);    //参数n指定缓冲区长度
  //返回值:若缓冲区足够大,返回将要存入数组的字符数;若出错,返回负值。

执行格式化输入处理的是3个scanf函数

#include <stdio.h>
int scanf(const char *restrict format,...);
int fscanf(FILE *restrict fp,const char *restrict format,...);
int sscanf(const char *restrict buf,const char *restrict format,...);
  //三个函数返回值:赋值的输入项数;若输入出错或在任一转换前已到达文件文件尾端,返回EOF。

 

10、临时文件

ISO C标准I/O库提供了两个函数以帮助创建临时文件

#include <stdio.h>
char *tmpnam(char *ptr);
  //返回值:指向唯一路径名的指针。
FILE *tmpfile(void);
  //返回值:若成功,返回文件指针;若出错,返回NULL。

tmpnam函数产生一个与现有文件名不同的一个有效路径名字符串,tmpfile创建一个临时二进制文件(类型wb+),在关闭该文件或程序结束时将自动删除。

 

参考:http://www.cnblogs.com/runnyu/p/4635382.html

猜你喜欢

转载自blog.csdn.net/m0_38099899/article/details/80082278