Linux基于流IO



基于流的I/O操作

       流的打开

函数:(1) FILE *fopen(const char *pathname,const char *type);

        (2) FILE *freopen(const char *pathname,const char *type, FILE *fp);

        (3) FILE *fdopen(int filedes,const char *type);

头文件:stdio.h

说明:

fopen函数用来打开一个特定的文件;

freopen用来在一个特定的流上打开一个特定的文件,当调用freopen时,首先关闭fp流,然后重新使用这个FILE结构指针fp打开pathname所代表的文件,此函数常用来对标准输入、标准输出、标准错误输出等预定义的流进行重定向。

fdopen用于将一个流和某一个已打开的特定文件相对应,filedes表示此文件的描述符,当只有type所定义的模式和filedes所表示的文件的打开模式相同时,调用才能成功。此函数多用于建立某一流和无法用于I/O操作函数的文件之间的关联,特别是管道文件和网络通信管道。

Type说明如下:

type

文件类型

是否新建

是否清空

可读

可写

读写位置

r

文本文件

NO

NO

YES

NO

文件开头

r+

文本文件

NO

NO

YES

YES

文件开头

w

文本文件

YES

YES

NO

YES

文件开头

w+

文本文件

YES

YES

YES

YES

文件开头

a

文本文件

NO

NO

NO

YES

文件结尾

a+

文本文件

YES

NO

YES

YES

文件结尾

rb

二进制文件

NO

NO

YES

NO

文件开头

r+b或rb+

二进制文件

NO

NO

YES

YES

文件开头

wb

二进制文件

YES

YES

NO

YES

文件开头

w+b或wb+

二进制文件

YES

YES

YES

YES

文件开头

ab

二进制文件

NO

NO

NO

YES

文件结尾

a+b或ab+

二进制文件

YES

NO

YES

YES

文件结尾

 

 

 

 

 

 

 

 

 

 

 

 

 

 

流的关闭

函数:int fclose(FILE *fp);

头文件:stdio.h

说明:调用成功返回0,调用失败返回-1,并设置errno的值,如果程序结束前没有执行流动关闭操作,有可能会造成写入的数据停留在缓冲区里没有保存到文件中,从而造成数据的丢失。

缓冲区类型

全缓冲区:该类型缓冲区要求填满整个缓冲区后才进行I/O操作,对于磁盘文件常使用全缓冲区访问。

行缓冲区:在该种模式下,当在输入和输出中遇到换行符时,标准I/O库执行I/O系统调用操作。当流涉及到一个终端时,使用行缓冲区。因为标准I/O库收集的每行的缓冲区长度为固定的,只要填满缓冲区,即使还没有遇到换行符,也将执行I/O系统调用。默认行缓冲区大小为128字节。

无缓冲区:标准I/O库不对字符进行缓存,如果用标准I/O函数写若干字符到不带缓冲区的流中,则相当于用write系统调用函数将这些字符写至相关联动打开文件。标准错误流通常不带缓冲区,从而能使错误信息尽快的显示出来。

设置缓冲区属性

函数:int setbuf(FILE *fp,char *buf);

       Int setbuffer(FILE *fp,char *buf,size_t size);

       Int setlinebuf(FILE *buf);

       Int setvbuf(FILE *fp,char *buf,int mode,size_t size);

头文件:stdio.h

说明:

l  setbuf函数用于将缓冲区设置为全缓冲或无缓冲,buf为指向缓冲区的指针。当buf指向一个真实缓冲区地址时,将缓冲区设置为全缓冲,大小有常数BUFSIZE指定,当buf为NULL时,则设定为无缓冲,此函数一般用作激活或禁止缓冲区的开关。

l  setbuffer函数与setbuf类似,区别在于可以有程序员设定缓冲区大小size。

l  setlinebuf用于将缓冲区设定为行缓冲区。

l  setvbuf的mode参数可以指定缓冲区类型,即: _IOFBF(全缓冲类型)、_IOLBF(行缓冲类型)、_IONBF(无缓冲类型 )。

一般而言需要在流打开但没有执行其他操作时候设定其类型,因为改变缓冲区类型会对所指向的操作参数影响。

缓冲区清空

函数:int fflush(FILE *fp);

头文件:stdio.h

说明:用于将缓冲区尚未写入文件的数据强制性的保存到文件中。

读取函数

函数:size_t fread(void *ptr,size_t size,size_t nmemb,FILE *fp);

头文件:stdio.h

说明:ptr为存储要读取数据的缓冲区,size 为读取记录的大小,nmemb是所读取记录的个数,fp为所要读取的流的文件FILE指针,其返回值为实际读取的记录个数。

写入函数

函数:size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE *fb);

头文件:stdio.h

说明:ptr为指向存放要输入数据的缓冲区指针,size为写入记录的大小,nmemb为所写记录的个数,fp为所要写入的流的文件FILE指针,其返回值为实际写入的记录个数。

文件结尾检查

函数:(1)int feof(FILE *fp); (2)ferror(FILE *fp);

头文件:stdio.h

说明:feof函数用来检测是否读到文件的结尾,当没有访问到文件的结尾时,返回为0,当访问到文件的结尾时,返回为1,只有执行读操作时候才对文件结束标志进行操作;ferror函数用来检测是否出现了读写错误,当访问正常接收时候,函数返回值为0,当访问非正常结束时,返回值为非0,并设置errno的值。此时errno的值为错误发生时由读写函数本身所设定的。

clearerr函数

函数:void clearer(FILE *fp);

头文件:stdio.h

说明:该函数当文件发生超过文件末尾读取或读写错误时来重置结束标志和错误标志。

rewind函数

函数: int rewind(FILE *stream);

头文件: stdio.h

说明: 将文件指针重新指向一个流的开头

fgetpos函数

函数: int fgetpos(FILE *stream);

头文件:stdio.h

说明: 取得当前文件的句柄

格式化输入输出

格式化输出

函数 :

(1) int printf(const *format,…);

   (2) int fprintf(FILE *fp,const char *format,…);

    (3) int sprintf(char *str,const char *format,…);

    (4) int snprintf(char *str,size_t size,const format,…);

(5) int vprintf(const *format,va_list ap);

(6) int vfprintf(FILE *fp,const char *format, va_list ap);

    (7) int vsprintf(char *str,const char *format, va_list ap);

    (8) int vsnprintf(char *str,size_t size,const format, va_list ap);

头文件:stdio.h

说明:

格式化输入

函数:

(1) int scanf(const char *format,…);

(2) int fscanf(FILE *fp,const char *format,…);

(3) int vsscanf(char *str,const char *format,…);

(4) int vscanf(const char *format, va_list ap);

(5) int vfscanf(FILE *fp,const char *format, va_list ap);

(6) int vsscanf(char *str,const char *format, va_list ap);

头文件:stdio.h

说明:

 

基于字符的输出

函数:

(1)int fputc(int c,FILE *fp);

(2)int putc(int c,FILE *fp);

(3)int putchar(int c);

头文件:stdio.h

说明:参数c表示要输出的字符;

 

ungetc函数

函数:int ungetc(int c,FILE *fp);

头文件:stdio.h

说明:用于将读入的字符再推回流中。

基于字符的输入

函数:

(4)int fgetc(FILE *fp);

(5)int getc(FILE *fp);

(6)int getchar(void);

头文件:stdio.h

说明:fgetc和getc的区别在于getc的参数是不能有副作用的表达式,而fgetc可以,getc比调用fgetc消耗时间少;getchar相当于以stdin为参数的getc函数。

 

基于行的输出

函数:(1) int fputs(const char *str,FILE *fp);

       (2)int puts(const char *str);

头文件:stdio.h

说明:

基于行的输入

函数:(1) char *fgets(char *str,int size, FILE *fp);

       (2) char *gets(char *str);

头文件:stdio.h

说明:

 

临时文件

临时文件是指那些在程序运行期间存在并使用,而当程序运行完之后就删除的文件,临时文件的操作都是在基于流的基础上进行的。

函数:(1)  char * tmpnam(char *str);

      (2)  char *tempnam(const char *directory,const char *prefix);

      (3) FILE *tmpfile(void);

头文件:stdio.h

说明:

    tmpnam作用是生成一个有效的文件名,该文件名不同于任何一个已经存在的文件名,str指向用于保存新生成文件名的缓冲区。该缓冲区长度要大于等于L_tmpnam,该常数在stdio库中定义。调用成功返回该缓冲区的指针,如果参数为NULL,则在静态缓冲区中存放生成的文件名,但是要再次调用该函数时将改变这一区域中的文件名,因此,,如果要保存文件名的话,必须要开辟相应的缓冲区来存放文件名。当调用失败是返回空指针。此外,tmpnam调用次数有所限制,必须小于等于TMP_MAX的值,该值在stdio库中定义。Tmpnam生产的文件名不能指定文件的路径和前缀,通常位于/tmp或/var/tmp目录下。

    Tempnam函数与tmpnam的区别在于它可以指定临时文件所在的目录。Directory可以指定文件的路径名,路径名的选取一般如下:如果已定义了环境变量TMPDIR,则使用TMPDIR,如果没有定义,directory不为空,则以directory所指向的缓冲区来做路径名。如果TMPDIR未定义,切directory为NULL,则以P_tmpdir为路径名,P_tmpdir由stdio定义,其优先级如下:

TMP>directory>P_tmpdir

Prefix为指定文件的前缀,当prefix不为NULL时,其所指向的缓冲区存放的字符串指定的前缀。其生成的文件名放在一块动态存储区中,有该函数调用malloc来分配,函数返回之西那个存放文件名的缓冲区指针,该文件使用完毕后,需要调用free来释放。

   tmpfile用于打开一个临时文件,该函数将创建一个临时二进制文件,该文件会在程序结束后自动删除,调用tmpfile生成临时文件时,它首先会调用函数tmpnam生产临时文件的文件名,然后创建这一文件,在程序结束时,系统调用ulink函数,文件将会删除


一,流与缓冲    

   流I/O是由C语言的标准函数提供的,这些I/O可以替代系统中提供的read和write函数。事实上流I/O的内部封装了这两个基本的文件读写系统调用。使用流I/O在某些程度上来讲要方便一些,这些I/O在效率上没有特别大的差异。

        基于流的操作最终会调用read或者write函数进行操作。为了使程序的运行效率最高,流对象通常会提供缓冲区,以减少调用系统I/O库函数的次数。

        基于流的I/O提供以下2种缓冲:

1,全缓冲:直到缓冲区填满,才调用系统I/O函数。对于读操作来说,直到读入的内容的字节数等于缓冲区大小或者文件以经到达结尾,才进行I/O操作将外存文件内容读入缓冲区;对于写操作来说,直到缓冲区填满,才进行实际的I/O操作将缓冲区内容写到外存文件中。磁盘文件通常是全缓冲的。

2,行缓冲:直到遇到换行符\n才调用系统I/O函数。对于读操作来说,遇到换行符\n才进行I/O操作,将所读内容写入缓冲区;对于写操作来说,遇到换行符\n才进行I/O操作,将缓冲区内容写到外存。由于缓冲区大小是有限制的,所以当缓冲区填满时即使没有遇到\n,也同样会进行实际的I/O操作。标准输入stdin和标准输出stdout都默认是行缓冲的。

3,无缓冲:灭有缓冲区,数据会立即读入或者输出到外存文件和设备上。标准出错stderr是无缓冲的,这样也能保证错误提示和输出能及时地反馈给用户,供用户排除错误。

二,基于文件流的操作

常用函数:

1,打开和关闭流

#include<stdio.h>

FILE*fopen(const char * restrict pathname,const char*restrict type);

FILE*fdopen(int fileds,const char*type);

fopen函数的第一个参数表示需要打开的文件的路径,第二个参数表示打开的方式。

fdopen函数用于在一个已经打开的文件上建立一个流,第一个参数是已打开文件的文件描述符,第二个参数是与fopen函数的第二个参数一样。只有一点不同的是,由于文件已经打开,所以fdopen函数不会再创建新文件,而且也不会将文件截短为0,这一点要热别注意,这两点在打开文件描述符的时候已经完成。

       Linux里用fclose函数关闭一个文件流,函数原型如下:

#include<stdio.h>

int fclose(FILE *fp);

如果执行成功,函数返回0,失败返回EOF,这个值在定义在stdio.h中,其值为-1。fclose函数关闭文件时,该函数会将保存在内存中未来得及写回到磁盘的文件内容写回到磁盘上。了解这一点很重要,如果没有调用fclose函数,就必 须等待内存中缓冲区被填满,由系统将其内容写回到磁盘上去。对于fclose函数是否需要检查返回值的问题困扰着许多程序员。虽然严格地说应该检查所有的 系统调用的返回值,并且进行错误处理,但对于fclose函数出错的几率很小,几乎为0.但如果去关闭一个网络环境中的远程文件,fclose函数就有可 能出错。由于fclose函数在关闭文件时会将缓冲区的内容写回到磁盘上,因此fclose函数实际是进行了一个写操作。在网络环境中,文件的内容是要通 过网络传输到目的主机上并写入磁盘上的。在这个传输过程中,如果网络链接出现问题或者传输数据出错,就会导致文件内容写入失败。这时fclose函数就会 出错。由此可知,如果在本地关闭一个文件可以不用检查返回值;如果在网络环境中关闭一个文件,检查fclose函数的返回值是有必要的

三,以字符为单位读写数据

       每次读写一个字符数据的I/O方式称为每次一个字符的I/O。Linux下使用fgetc函数获得一个字符,其函数原型如下:

             #include<stdio.h>

             int fgetc(FILE*fp);

函数如果执行成功则返回该字符的ASCLL值,如果执行失败,则返回EOF。

Linux环境下使用fputc函数输出一个字符数据,函数原型如下:

#include<stdio.h>

int fputc(int c,FILE*fp)

第一个参数表示想要输出的字符的ASCLL值(源),第二个参数表示想要输出的文件流(目的地)。

四,以行为单位读写数据

      当输入内容遇到\n时则将流中\n之前的内容送到缓冲区中的I/O方式称为每一次行的I/O。Linux使用下列函数提供一次读入一行的功能。

#include<stdio.h>

char*fgets(char *restrict buf,int n,FILE*restrict fp);

char*gets(char*);

fgets函数的第一个参数表示存放读入的缓冲区,第二个参数n表示读入的字符个数,此参数的最大值不能超过缓冲区的长度。fgets函数一直读,直到遇到\n为止,如果在n-1个字符內未遇到换行符,则只读入n-1个字符。最后一个字符用于存储字符串结束标志\0.需要注意的是fgets函数会将‘\n’换行符也读进缓冲区中,因此缓冲区的实际有效内容应该是缓冲区实际字节数(不包括‘\0’)减1.fgets函数的第三个参数是需要读入的流对象。

          fgets函数的换回值有以下两种情况:1,成功读取一行,返回缓冲区的首地址。2,读取出错或者文件已经到达结尾则返回NULL。

gets函数和fgets函数类似,该函数从标准输入流中读取一行并将其存入一个缓冲区,并不将‘\n’读进缓冲区中。gets函数的返回值和fgets相同。

       Linux 环境下用fputs函数和puts函数实现输出一行字符串,其函数原型如下:

#include<stdio.h>

int fputs(const char*restrict str,FILE *restrict fp);

int puts(const char*str);

fputs函数的第一个参数表示存放输出内容的缓冲区,第二个参数表示要输出的文件。如果执行成功则返回输出的字节数,失败返回-1。puts函数用与向标准输出输出一行字符串,其参数和fputs函数的第一个参数相同,如果成功输出,则返回输出的字节数,失败则返回-1,值得注意的是,虽然gets函数不读入\n,但是puts函数却输出\n。fputs和puts函数都不输出字符串的结束符‘\0’。对于I/O来说,fputs函数和fgets函数的搭配是安全又可靠的。

       五,gets函数的漏洞

gets函数和fgets函数最大的不同是gets函数的缓冲区虽然由用户提供,但是用户无法指定其一次最多读入多少个字节的内容。这一点导致gets函数变成了一个危险的函数


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值