Unix环境高级编程学习笔记(三)

第五章 标准IO库
1、流和FILE对象:
有两个函数可以改变流的定向:freopen函数可以清除一个流的定向;fwide函数可以设置流的定向
#include<stdio.h>
#include<wchar.h>   
int fwide(FILE *fp, int mode);    //若流是宽定向的则返回正值,若流是字节定向的则返回值负值,未定向返回0
若mode为负,字节定向;mode为正,宽定向;mode为0,不定向。    fwide并不改变已定向流的定向,无出错返回。
当打开一个流时,标准IO函数fopen返回一个指向FILE对象的指针,该对象是一个结构,包含了标准IO库为管理该流所需的所有信息,包括:文件描述符,该流的缓冲区指针,缓冲区长度等等。我们称FILE*对象为文件指针。

2、标准输入、标准输出、标准出错:stdin、stdout、stderr,定义在<stdio.h>中,注意这三个对象是流。

3、缓冲:全缓冲、行缓冲、不带缓冲
我可以调用以下两个函数更改缓冲类型:#include<stdio.h>
                             void setbuf(FILE* restrict fp, char *restrict buf);
                 int setvbuf(FILE* restrict fp, char* restrict buf, int mode, size_t size);     成功返回0,否则返回非0值
这些函数一定要在流打开后调用,而且要在对该流执行任一操作之前执行。
可以使用setbuf打开或关闭缓冲机制。      使用setvbuf可以精确指定缓冲类型,用mode参数指定:_IOFBF 全缓冲   _IOLBF 行缓冲  _IONBF 不带缓冲
如果指定不带缓冲,则忽略buf和size参数。如果指定行缓冲或全缓冲,buf和size可指定一个缓冲区及其长度。
强制冲洗一个流:#include<stdio.h>      int  fflush(FILE* fp);    

4、打开流:#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 filedes, const char* type);
区别:(1)fopen打开一个指定文件  (2)在一个指定的流(如标准输入)上打开指定文件     (3)用文件描述符打开流
type指定打开方式:r或rb(为读打开),w或wb(把文件截短为0,或为写而创建),a或ab(添加;或为写而创建),r+或r+b或rb+(为读和写而打开),w+或w+b或wb+(把文件截短为0,或为读写打开),a+或a+b或ab+(为在文件尾读和写而打开和创建)       默认设置流打开是全缓冲。
可以用fclose关闭一个打开的流:#include<stdio.h>    int fclose(FILE* fp);

5、读和写流:(1)每次一个字符;(2)每次一行;(3)、直接IO
(1)#include<stdio.h>    int getc(FILE* fp);    
              int fgetc(FILE *fp);
              int getchar(void);     等价于getc(stdin)            成功返回下一个字符,出错或到结尾返回EOF
区分出错或到达文件结尾:#include<stdio.h>     int ferror(FILE* fp);       int feof(FILE *fp);    若条件为真返回非0值
                                         void clearerr(FILE *fp);     清除出错标志和文件结束标志。
从流中读取数据以后可以调用ungetc将字符再压送回流中:#include<stdio.h>     int ungetc(int c, FILE *fp);
(2)输出函数:
对应上面所说的每个输入函数读有一个输出函数:#include<stdio.h>    int putc(int c, FILE* fp);     int fputc(int c, FILE *fp);    int putchar(int c);(等价于putc(c, stdout))

6、每次一行I/O:#include<stdio.h>  
          char *fgets(char *restrict buf, int n, FILE *restrict fp);
          char *gets(char *buf);(不推荐使用)
每次输出一行:int fputs(const char *restrict str, FILE *restrict fp);
            int puts(const char *str);(每次会在结尾自动加换行符,虽然安全,但依然推荐避免使用)。

7、标准IO的效率:略。

8、二进制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);       返回读或写的对象个数
 用途:(1)读写一个二进制数组:float data[10];    
                 if(fwrite(&data[2], sizeof(float), 4, fp) != 4)     
                    printf("fwrite error!");   (将一个浮点数组写至一个文件上)
    (2)读或写一个结构:struct{short count; long total; char name[NAMESIZE];}item;
                 if(fwrite(&item, sizeof(item), 1, fp) != 1)
                     printf("fwrite error!");
9、定位流:有三种方法定位标准I/O流:(1)ftell和fseek函数。(2)ftello和fseeko函数。(3)fgetpos和fsetpos函数。   注:要移植到非unix系统,需使用fgetpos和fsetpos
#include<stdio.h>
long ftell(FILE *fp);            成功返回当前位置,出错返回-1
int fssek(FILE *fp, long offset, int whence);    成功返回0,出错赶回非0值
void rewind(FILE *fp);     将流设置到文件的起始位置
  whence:SEEK_SET:文件开头;SEEK_CUR:当前文件位置;SEEK_END:文件尾端。    
off_t ftello(FILE* fp);       
int fseeko(FILE *fp, off_t offset, int whence);
  除了offset的类型是off_t而非long外,其他方面于上面两个函数相同。
int fgetpos(FILE *restrict fp, fpos_t *restrict pos);
int fsetpos(FILE *fp, const fpos_t *pos);

10、格式化I/O
(1)格式化输出
#include<stdio.h>
int printf(const char *restrict format, ...);       写到标准输出
int fprintf(FILE *restrict fp, const char *restrict format, ...);      写至指定流
int sprintf(char* restrict buf, const char restrict format, ...);      写至数组buf,不安全
int snprintf(char *restrict buf, size_t n, const char *restrict format, ...);       写至数组buf,安全
格式化说明:p123
还有4个printf的变种:vprintf,vfprintf,vsprintf,vsnprintf
(2)格式化输入
#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, ...);
3个变种:#include<stdio.h>  #include<stdarg.h>  vscanf, vsscanf, vfscanf

11、实现细节:
获得流的描述符:#include<stdio.h>  int fileno(FILE *fp);
程序清单5-3能够用程序确定一个流是全缓冲还是行缓冲还是不带缓冲。

12、临时文件:
有两个函数能够帮助创建临时文件:#include<stdio.h>     char *tmpnam(char *ptr);       FILE *tmpfile(void);
程序清单5-4演示这两个函数的用法。
两个扩展函数:#include<stdio.h>    char *tempnam(const char *directory, const char *prefix);     允许调用者为所产生的路径名指定目录和前缀。
              #include<stdlib.h>   int mkstemp(char *template);   类似于tmpfile,但是该函数返回文件描述符,而且临时文件不会自动被删除
可以用tmpfile和mkstemp函数取代tmpnam和tempnam函数

posted @ 2011-07-31 20:34  name_110  阅读(569)  评论(0编辑  收藏  举报