标准IO

一、关于标准IO缓冲区

标准IO提供缓冲的目的是尽可能减少使用read和write调用的此数,他对每个IO流自动地进行缓冲管理。标准IO提供三种类型的缓冲:
1、全缓冲:这种情况下,当标准IO缓冲区填满后才进行实际IO操作。在一个流上执行第一次IO时,相关标准IO函数通常调用malloc获得所需的缓冲区。全缓冲的缓冲区大小一般为8192(具体要看设置)
2、行缓冲:当输入和输出中遇到换行符‘\n’时,才会执行实际IO操作。当涉及一个终端时(例如标准输入和标准出错),通常使用行缓冲。
因为标准IO库用来收集每一行的缓冲区的长度是固定的,所以只要行缓冲区满了,即使还没有写一个换行符,也会进行IO操作
3、不带缓冲:标准IO库不对字符进行缓冲存储,只要执行了输入和输出操作,便会立即实行IO操作。标准出错stderr通常是不带缓冲的。

对于进程预定义了三个流,并且这三个流可以自动地被进程使用:
标准输入:stdin
标准输出:stdout
标准出错:stderr

ISO  C要求下列缓冲特征:
当且仅当标准输入和标准输出并不涉及交互式设备时,它们才是全缓冲。否则一般为行缓冲。
人机交互要求不可全缓冲。
标准出错绝不会是全缓冲的
涉及终端设备的其他流,一般为行缓冲的,否则是全缓冲。
普通文件一般为全缓冲


可以使用下面两个函数更改缓冲类型:

void setbuf(FILE *stream, char *buf);
功能:更改流的缓冲类型
参数:
          stream:要更改缓冲类型的流指针
          buf:缓冲区的长度,通常指定为BUFSIZ,通常在此之后流就是全缓冲的。如果为NULL,则关闭缓冲。
返回值:成功返回0,错误返回非0值

int setvbuf(FILE *stream, char *buf, int mode, size_t size);
功能:更改流的缓冲类型
参数:
            stream:要更改缓冲类型的流指针
             buf:如果被设置为不带缓冲的流,则忽略buf和size,如果指定了全缓冲或行缓冲,buf指定了缓冲区的地址,size指定了缓冲区的长度。如果buf为NULL,系统自动分配全缓冲区或行缓冲区合适的长度。
             mode:
                           指定所需的缓冲类型    
                            _IOFBF         全缓冲
                            _IOLBF          行缓冲
                            _IONBU        不带缓冲
             size:缓冲区大小
返回值: 成功返回0,错误返回非0值

int fflush(FILE *stream);
功能:冲洗一个流,此函数使该流所有未写的数据都被传送至内核
参数:
        stream:要冲洗的流,如果为NULL,则冲洗所有输出流
返回值:成功返回0,失败返回EOF

冲洗说明标准IO缓冲区的写操作,flush有两种意思,在标准IO库方面,flush意味着将缓冲区的内容写到磁盘上。在终端驱动程序方面,flush表示丢弃已存储在缓冲区的数据


二、流的定向
对于ASCII字符集,一个字符用一个字节表示,对于国际字符集,一个字符可用多个字节表示。标准IO文件流可用於单字节或多字节(宽)字符集。流的定向决定了所读写的字符是单字节还是多字节。当一个流最初被创建时,它并没有定向。如若在未定向的流上使用一个多字节IO函数,则将该流的定向设置为宽定向。如若在未定向的流上使用一个单字节IO函数,则将该流的定向设置为字节定向。
可用以下函数设置流的定向:

int fwide(FILE *stream, int mode);
功能:设置一个未定向流的定向
参数:
                    stream:要改变定向的流
mode:
为负值时,试图将指定的流设置为字节定向
为正值时,试图将指定的流设置为宽定向
为0时,不设置流的定向,但返回标示该流定向的值
返回值:若流是宽定向的则返回正值,若流是字节定向的则返回负值,若流是未定向的,则返回0。无出错返回
注:fwaid只能改变未定向的流。并不改变已定向的流


三、标准IO的一些函数
FILE *fopen(const char *path, const char *mode);
功能:打开一个指定文件,返回一个标准IO流
参数:
        path:文件所在路径
        mode:打开方式
                    r:只读方式打开,打开后从文件头开始读
                    r+:读写方式打开,打开后从文件头开始读写
                    w:只写方式打开,文件不存在则创建,存在则把文件截短至0,即将文件清空
                    w+:读写方式打开,文件不存在则创建,存在则把文件截短至0,即将文件清空
                    a:只写打开,文件不存在则创建,存在以只写方式追加,即从文件尾部开始写
                    a+:读写方式打开,文件不存在则创建,存在则读文件时从文件头开始,写文件时从文件尾开始
当指定参数b时,表示以二进制方式打开,不过因为UNIX不对文本文件和二进制文件进行区分,所以在UNIX环境下指定b实际上并无作用
返回值:成功返回流指针,失败返回NULL

FILE *freopen(const char *path, const char *mode, FILE *stream);
功能:在一个指定的流上打开一个指定的文件,如若该流已经打开,则先关闭该流。若该流已经定向,则freopen清除该定向。此函数一般用于将一个指定的文件打开为一个预订义的流:标准输入,标准输出或标准出错。
参数:
                 path:文件所在路径
                 mode:  
                    r:只读方式打开,打开后从文件头开始读
                    r+:读写方式打开,打开后从文件头开始读写
                    w:只写方式打开,文件不存在则创建,存在则把文件截短至0,即将文件清空
                    w+:读写方式打开,文件不存在则创建,存在则把文件截短至0,即将文件清空
                    a:只写打开,文件不存在则创建,存在以只写方式追加,即从文件尾部开始写
                    a+:读写方式打开,文件不存在则创建,存在则读文件时从文件头开始,写文件时从文件尾开始
当指定参数b时,表示以二进制方式打开,不过因为UNIX不对文本文件和二进制文件进行区分,所以在UNIX环境下指定b实际上并无作用

                  stream:要在此流上打开文件
返回值:成功返回流指针,失败返回NULL

FILE *fdopen(int fd, const char *mode);
功能:将一个现有的文件描述符和一个标准IO流相结合
参数:
         fd:一个已经打开的文件描述符
         mode:
                    和fopen一样,不过此函数为写打开时,并不将文件清空。另外追加方式也不能创建该文件(因为文件已经存在)
        
返回值:成功返回生成的流指针,失败返回NULL
注:此文件描述符必须是一个已经打开的文件描述符


四、标准IO读写

int fgetc(FILE *stream);
功能:从指定的流中丢读取字符
参数:stream:要读取的流
返回值:成功返回字符,失败或读到文件尾部返回EOF(-1)


int fputc(int c, FILE *stream);
功能:向指定的流中写一个字符
参数:
c:要写入的字符
stream:要写入的流
返回值:成功返回写的字符,错误返回EOF


char *fgets(char *s, int size, FILE *stream);
功能:从指定的流读取多个字符存放在s指向的地址,每次读一行,以一个换行符终止
参数:
            s:将读取到的数据存放到s中
            size:缓冲区长度
            stream:要读取的文件流
返回值:成功返回s,失败或读到结尾返回NULL
注:
  • 每次fgets最多只能读取size-1个字符,因为每次读取结束时都会自动加‘\0’
  • 如果读取过程中遇到‘\n’,则读取结束,'\n'会被读走


int fputs(const char *s, FILE *stream);
功能:将字符串写到指定的流
参数:
          s:s中存放将要写入的数据
          stream:要写的文件流
返回值:成功返回写入的字符个数,失败返回EOF
注:如果遇到‘\n’则结束写


size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从指定的流读取多数据存放在ptr指向的地址
参数:
          ptr:将已读取的数据存放到ptr中
          size:要读取对象的大小
          nmemb:要求读取对象的个数
          stream:要读取的流
返回值:返回实际读取的对象的个数


size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
功能:将数据写向指定的流
参数:
          ptr:存放要写入的数据存放在ptr中
          size:要写入数据的对象的大小
          nmemb:要求写入数据的对象的个数
          stream:要写入的流
返回值:返回实际写入的对象的个数,如果返回值小于所要求的nmemb,则出错

注:

1、在上面的三个读操作中,不区分出错和到达文件尾,为了区分这两种情况,需调用以下两个函数
int feof(FILE *stream);
int ferror(FILE *stream);
两个函数的返回值:若条件为真则返回非0值。否则返回0

2、在大多数实现中,为每个流在FILE对象中维持了两个标志:
  • 出错标志
  • 文件结束标志 
     调用clearerr清除这两个标志 
    void clearerr(FILE *stream);

3、从流中读取数据以后可以调用ungetc将字符再压送回流中
        int ungetc(int c, FILE *stream);
         参数:c:要回送的字符
                    stream:要回送的流
         返回值:成功返回c,出错返回eof
        
        压送回流中的字符以后又可从流中读出。ISO C允许实现支持任何次数的回送,但是它要求时限提供一次只送回一个字符,我们不能期望一次能送回多个字符
        回送的字符不必一定是上一次读到的字符,参数c既可以是上次读出的字符,也可以是任意别的字符,但不能回送EOF。但是当已经到达文件尾端时,仍可以回送一个字符,下次读将返回该字符,再次读则返回EOF。之所以能这样做的原因是一次成功的ungetc调用会清除该流的文件结束标志。



五、文件定位

int fseeko(FILE *stream, off_t offset, int whence);
int fseek(FILE *stream, long offset, int whence);
功能:更改内核中offset的值
参数:
            stream:要更改的文件流
            offset:偏移值。offset>0,向后偏移,offset<0,向前偏移。
            whence:
                    SEEK_SET  从文件其实位置开始
                    SEEK_CUR 从文件当前位置开始
                    SEEK_END 从文件尾端开始
返回值:成功返回0,失败返回-1
注:上述两个函数的区别仅在于文件偏移量的类型不一样,一个时是long,一个是off_t


off_t ftello(FILE *stream);
long ftell(FILE *stream);
功能:获得内核中的文件偏移量
参数:stream:要获取偏移量的文件流
返回值:成功返回文件从头开始的偏移值,失败返回-1
注:上述两个函数的区别仅在于文件偏移量的类型不一样,一个时是long,一个是off_t

void rewind(FILE *stream);
功能:定位到文件起始位置
参数:stream:要定位的文件流

  
int fileno(FILE *stream);
功能:获得与流相关联的文件描述符
参数:stream:要获取描述符的流
返回值:返回与流相关联的文件描述符


六、临时文件

char *tmpnam(char *s);
功能:产生一个与现有文件名不同的一个有效路径名字符串
参数:s:如果为NULL,则将产生的路径名存放在一个静态区中。指向该静态区的指针作为函数值返回。下一次再调用该函数时,会重写该静态区。如果s不是NULL,则将产生的路径名存放在s指向的空间中,s作为函数返回值。
返回值:指向唯一路径名的指针

FILE *tmpfile(void);
功能:创建一个临时二进制文件(wb+),在关闭文件或进程结束时    将自动删除这种文件
返回值:成功返回文件流指针,出错返回NULL


























发布了44 篇原创文章 · 获赞 14 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章