标准IO

标准I/O - 介绍

不仅在UNIX系统,在很多操作系统上都实现了标准I/O

标准I/O库由ANSI C标准说明

标准I/O库处理很多细节,如缓存分配、以优化长度执行I/O等,这样使用户不必关心如何选择合适的块长度

标准I/O在系统调用函数基础上构造的,它便于用户使用

标准I/O库及其头文件stdio.h为底层I/O系统调用提供了一个通用的接口。

文件指针

FILE指针:每个被使用的文件都在内存中开辟一个区域,用来存放文件的有关信息,这些信息是保存在一个结构体类型的变量中,该结构体类型是由系统定义的,取名为FILE

标准I/O库的所有操作都是围绕流(stream)来进行的,在标准I/O中,流用FILE *来描述。

标准I/O库是由Dennis Ritchie1975年左右编写的

流(stream

定义:所有的I/O操作仅是简单的从程序移进或者移出,这种字节流,就称为流。

分类:文本流/二进制流。

文本流

定义:在流中处理的数据是以字符出现。在文本流中,’\n’被转换成回车符CR和换行符LFASCII0DH0AH。而当输出时,0DH0AH被转换成’\n’

数字2001在文本流中的表示方法为  ‘2’  ‘0’  ‘0’  ‘1’

                        ASCII:    50  48  48  49

二进制流

定义:流中处理的是二进制序列。若流中有字符,则用一个字节的二进制码表示;若是数字,则用对应的二进制数表示。对’\n’不进行变换

数字2001在二进制流中的表示方法为 00000111  11010001

缓冲文件系统(高级磁盘IO)

目的:尽量减少使用read/write的调用

定义:系统自动的在内存中为每一个正在使用的文件开辟一个缓冲区,从内存向磁盘输出数据必须先送到内存缓冲区,装满缓冲区在一起送到磁盘中去。从磁盘中读数据,则一次从磁盘文件将一批数据读入到内存缓冲区中,然后再从缓冲区逐个的将数据送到程序的数据区。

分类:全缓存,行缓存,不缓存。

非缓冲文件系统 (低级磁盘IO

定义:依靠于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出。

标准I/O提供了三种类型的缓存

全缓存

当填满I/O缓存后才进行实际I/O操作,或者满足一定条件后,系统通过调用malloc来获得所需要的缓冲区域,默认值。

刷新(fflush):标准I/O的写操作。

当缓冲区满了,或者满足一定的条件后,就会执行刷新操作。

行缓存

当在输入和输出中遇到新行符(‘\n’)时,进行I/O操作。

当流遇到一个终端时,典型的行缓存。

不带缓存

标准I/O库不对字符进行缓冲,例如stderr

很多的人机交互界面要求不可全缓存。

标准出错决不会是全缓存的。

使用setbuf()setvbuf()可以更改缓存的类型

在任何时刻,可以使用fflush强制刷新一个数据流

标准I/O – fflush()

定义:

#include <stdio.h>

int fflush(FILE *fp);

说明:

可强制刷新一个流。此函数使该流所有未写的数据都被传递至内核。

标准I/O - stdin,stdout,stderr

标准I/O预定义3个流,他们可以自动地为进程所使用

在启动程序时,有三个文件流是自动打开的。它们是stdinstdoutstderr。它们都是在stdio.h头文件里定义的,分别代表着标准输入、标准输出和标准错误输出,与底层文件描述符012相对应。 

下列三个函数可用于打开一个标准I/O流:

FILE *fopen (const char *path, const char *mode);

FILE *freopen(const char *restrict pathname, const char *restrict type, FILE* restrict fp)

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

标准I/O - fopen() - mode参数

打开标准I/O流的mode参数:

当给定“b”参数时,表示以二进制方式打开文件,+”表示文件可读写,“r”表示文件必须存在,wa表示创建文件。

标准I/O-fclose()

fclose()用于关闭一个已经打开的流:

int fclose(FILE *stream)

fclose()调用成功返回0,失败返回EOF,并设置errno

在该文件被关闭之前,刷新缓存中的数据。如果标准I / O库已经为该流自动分配了一个缓存,则释放此缓存。

当一个进程正常终止时(直接调用exit函数,或从main函数返回),则所有带未写缓存数据的标准I / O流都被刷新,所有打开的标准I / O流都被关闭。

在调用fclose()关闭流后对流所进行的任何操作,包括再次调用fclose(),其结果都将是未知的。

标准I/O-读写流

调用fopen()成功打开流之后,可在三种不同类型的非格式化I/O中进行选择,对其进行读、写操作:

每次一个字符的I/O。使用fgetc()/fputc()一次读或写一个字符,如果流是带缓存的,则标准I/O函数处理所有缓存。

每次一行的I/O。使用fgets()fputs()一次读或写一行。每行都以一个新行符终止。当调用fgets()时,应说明能处理的最大行长。

直接I/Ofread()fwrite()函数支持这种类型的I/O。每次I/O操作读或写某种数量的对象,而每个对象具有指定的长度。这两个函数常用于从二进制文件中读或写一个结构。

标准I/O-读写流

#include<stdio.h>
int getc( FILE *file_p );
int fgetc( FILE *file_p );
int getchar( void );
getcfgetc的区别是:getc可以被实现为宏,fgetc不能被实现为宏。这意味着:
1 getc的参数不应当是具有副作用的表达式;
2 fgetc是一个函数,可以将fgetc的地址作为一个参数传递给另一个函数;
调用fgetc的时间通常长于调用getc
为了区分出错还是到达文件尾端,必须调用ferrorfeof
#include<stdio.h>
int ferror( FILE *file_p );
int feof( FILE *file_p );
void clearerr( FILE *file_p );

#include<stdio.h>
int ungetc( int c, FILE *file_p );
ungetc将字符压送回流中,一次只送回一个字符。回送的字符不必一定是上次读到的字符。不能回送EOF。但是当到达文件尾时,仍可以回送一个字符,因为一次成功的ungetc调用会清除该流的文件结束符标志。

#include<stdio.h>
int putc( int c, FILE *file_p );
int fputc( int c, FILE *file_p );
int putchar( int c );
与输入函数一样,putc可以实现为宏,而fputc却不能。 

标准I/O-读写流-二进制I/O

#include<stdio.h>
size_t fread( void *restrict ptr, size_t size, size_t nobj, FILE *restrict file_p );
size_t fwrite( const void *restrict ptr, size_t size, size_t nobj, FILE *restrict file_p ); 

两个函数的返回:读或写的对象数

对于二进制数据我们更愿意一次读或写整个结构。

为了使用getc()putc()做到这一点,必须循环读取整个结构,一次读或写一个字节。(效率低)

fputs()在遇到null字节时就停止,而在结构中可能含有null字节,所以不能使用每次一行函数实现这种要求。如果输入数据中包含有null字节或换行符,则fgets()也不能正确工作。(实现限制)

标准I/O-定位流

定位标准I/O流的两种方式

ftell()fseek(): 这两个函数自V7以来就存在了,但是它们都假定文件的位置可以存放在一个长整型中。

fgetpos()fsetpos()。这两个函数是新由ANSI C引入的。它们引进了一个新的抽象数据类型fpos_t,它记录文件的位置。

需要移植到非UNIX系统上运行的应用程序应当使用fgetpos()fsetpos()

标准I/O-定位流

#include<stdio.h>
long ftell( FILE *file_p );
int fseek( FILE *file_p, long off_set, int whence );
这两个函数假定文件的位置可以存放在一个长整型中。
void rewind( FILE *file_p );

off_t ftello( FILE *file_p );
int fseeko( FILE *file_p, off_t off_set, int whence );
这两个函数用off_t数据类型替代了长整型。

int fgetpos( FILE *restrict file_p, fpos_t *restrict pos );
int fsetpos( FILE * file_p, const fpos_t *pos );
这两个函数是ISO C引进的。

ftell()用于取得当前的文件位置,调用成功则为当前文件位置指示,若出错则为-1L

fseek()用户设定stream流的文件位置指示,调用成功返回0,失败返回-1,并设置errno

fseek()whence参数:SEEK_SET/ SEEK_CUR/ SEEK_END

rewind()用于设定流的文件位置指示为文件开始,该函数调用成功无返回值。

rewind()等价于(void)fseek(stream, 0L, SEEK_SET)

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

需要移植的程序,应该优先考虑fgetpos()/fsetpos()

I/O模型比较

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值