chapter 5 标准I/O库

     标准I/O库主要是由ANSI C实现的。主要是为了在不同操作系统上实现。

     在UNIX中,标准I/O库的最终都要调用I/O例程。

     标准I/O库的操作都是围绕stream来进行的。与流相对应的是FILE对象的指针,这个FILE对象的指针和file描述符是有差别的,这是一个结构体,定义在stdio.h中,不同于file描述符就是一个int型数据。

     预定义的stream是有三个:stdin,stdout,stderr。对应的文件描述符分别是:STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO。

     缓存分三种:_IOFBF,_IOLBF,_IONBF,全缓存,行缓存,没有缓存。默认的,stdin和stdout是行缓存,stderr是不带缓存。缓存类型是可以设置的:

     #include <stdio.h>

     void setbuf(FILE* fp, char* buf);

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

     其中,setbuf有buf来决定是否带缓存,而setvbuf是通过mode来决定是哪一种缓存,而buf来决定是用户缓存还是系统缓存,如果是系统缓存,则size是没有意义的。系统缓存的size是由系统决定的,可能是st_blksize,也可能是BUFSIZE。这个由系统来决定。

     流可以直接刷新,可以强制刷出:

     #include <stdio.h>

     int  fflush(FILE* fp);

     一个通用的过程应该是:打开---->读写----->关闭,其他还有 定位, 格式化I/O, 临时文件。

     打开:

     #include <stdio.h>

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

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

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

其中,freopen 在一个特定的流上打开一个指定的文件。此函数一般用于将一个指定的文件打开为一个预定以的流:stdin,stdout,stderr。

fdopen则是把filedes转为FILE*。

type是规定读写方式:r w a +

b在unix内核中不起作用,因为内核不区分文本文件和2进制文件。

    对应的关闭:

    int fclose(FILE* fp);

    正常终止进程,流会被flush,并关闭。


    读写分为三种:

1,字符读写:

#include <stdio.h>

int getc(FILE* fp);

int fgetc(FILE* fp);

int getchar(void);


int putc(int c, FILE* fp);

int fputc(int c, FILE* fp);

int putchar(int c);

其中,getchar是getc的特殊形式,fp是stdin。putchar是putc的特殊形式,fp是stdout.

getc和putc可以用宏实现,所以会快一些。而fgetc和fputc可以作为函数参数。

getc和fgetc是返回值在出错和文件结尾的时候都返回EOF,可以用如下函数判断:

int ferror(FILE* fp);

int feof(FILE* fp);

清除标志用:

int clearerr(FILE* fp);

获取字符可以回送,取出来看一下,然后送回去,想用的话在get:

int ungetc(int c, FILE* fp);

EOF不能回送。


2 行读写:

#include <stdio.h>

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

char* gets(char* buf);


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

char* puts(const char* str);

其中,gets可能会出现缓存越界。fgets读取n-1个字符。

fputs将一个以null符终止的字符串写到指定的流,null 不写出。


3 二进制读写:

这个主要是读取一个结构体(包括数组)之类的完整数据。

#include <stdio.h>

size_t fread(void* ptr, size_t size, size_t nobj, FILE* fp);

size_t fwrite(const void* ptr, size_t size, size_t nobj, FILE* fp);

跨系统很难工作。


打开-->读写-->关闭,然后就是定位

1 unix系统老的方法:

#include <stdio.h>

long ftell(FILE* fp);

int fseek(FILE* fp, long offset, int whence);

void rewind(FILE* fp);

其中,rewind定位到0;

whence可以是: SEEK_SET,SEEK_CUR,SEEK_END.

事实上,文本文件不能单纯的用long值来表示。


2 ANSI C引入的:

#include <stdio.h>

int fgetpos(FILE* fp, fpos_t* pos);

int fsetpos(FILE* fp, const fpos_t* pos);


格式化I/O:

#include <stdio.h>

int printf(const char* format, ......);

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

int sprintf(char* buf, const char* format, ......);


int scanf(const char* format, ......);

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

int sscanf(const char* buf, const char* format, ......);

其中,sprintf可能会越界,必须有调用者来控制。

输出有一个变种如下:

#include <stdio.h>

#include <stdarg.h>

int vprintf(const char* format, va_list arg);

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

int vsprintf(char* buf, const char* format, va_list arg);


之前有将filedes转为FILE*的,

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

反之:

     int fileno(FILE* fp);


临时文件

#include <stdio.h>

char* tmpnam(char* ptr);

FILE* tmpfile(void);

其中,tmpnam中ptr和返回值是一致的。ptr如果是null,再次调用该函数时是会重写原先的文件名的,所以如果想保存是不能仅保存指针的。

变种:

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

临时文件的目录有一个顺序,最好就直接用这个函数规定就好了。

TMPDIR>directory>P_tmpdir>/tmp


本章基本就是这些内容了。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章