5.1FILE & 流
- I/O 中操作都围绕stream进行,打开或创建一个文件是通常用一个流与文件绑定!
- FILE 文件对象,里面包含文件的缓冲区地址、缓冲区大小、缓冲区中的字符数、出错标志等!
- 有些系统在缓冲区中保存,控制管理信息,so可能实际缓冲区大小比指定size小!
- 流有单字节流& 多字节流(国际字符集多字符),称为流的定向
- 刚创建的流没有流定向
- 为定向的流上使用单字符(多字符)I/O函数则是但字符(多字符)流!
- 可用fwide(FILE *fp, int mode);指定流定向, freopen 清楚定向
mode 负数--->单字符流
正数---->多字符刘
0 ----> 未指定,但是返回的值标示给流定向的值(?)
无出错返回,只能有errno,so 调用钱清除errno
5.4缓冲
全缓冲
读写是缓冲区满才进行I/O,缓冲区大小BUFSIZ<stdio.h>
行缓冲
- 遇到换行符时进行实际I/O操作,终端设备通常为行缓冲
- 缓冲区满,不管有无换行都读写
- 第三点没怎么看明白,p116
不带缓冲
- 字符读写立即写到文件中!
- stderr通常为NOBUF
处理函数
#include<stdio.h>
void setbuf(FILE *restrict fp, void *restrit buf);//
- 设置fp的缓冲地址为buf, buf大小必须为BUFSIZ<stdio.h>
- buf==NULL则关闭缓冲
void setvbuf(FILE *restrict fp, void *restrit buf, int mode, int size);
mode :_IOFBF
_IOLBF
_IONBF
size 指定buf的大小
若fp==NULL 按BUFSIZ 调用malloc分配
系统自动分配的缓冲区,在流关闭时会自动释放缓冲区
IOC 要求标准输入输出文件,为非交互式设备是,为非全缓冲
通常终端设备是行缓冲
标准错误通常不带缓冲!
5.5打开流
#include<stdio.h>
FILE *fopen(const char*restrict pathname, const char *restrict type);
在给定目录下打开文件I/O流
FILE *freopen(const char *restrict pathname, const char *restrict type, FILE *restrict fp);
- 在给定的流上打开指定文件,按type设定模式
- fp已经打开,先关闭流
- fp有流定向,清除流定向
- fp的打开模式优先于type的打开模式
FILE *fdopen(int fd, const char *restrict type);
- 在给定文件描述符上打开I/O流
- fp可能是socket、piped,dup等,这些不能用fopen打开,需要先使用设备函数获得文件描述符!
type
r rb 只读
w wb 只写
a ab O_APPEND
r+ rb+
w+ wb+
a+ ab+
+号表示,可读可写(或者说,非定向的,根据实际读写使用情况,确定流用来读或者写,在保证读写正确的情况下,读写都ok),
- 若果最开始在流上读,在fseek、fpos、rewind没调用下则EOF前不能写
- 最开始在留上写,则在fflush、fseek、fpos、rewind没调用下(这些操作说明本阶段写操作完毕,读不会与写冲突),写之后不能读
- 读之前文件必须存在,w会截断
fclose(FILE *fp);//fp==NULL 则flush所有流
进程正常终止(exit,main返回),所有流flush.I/O关闭!
5.6读写流
int getc(FILE *fp);//宏,so不能有副作用的表达式,如函数调用神马的,可能调用多次
int fgetc(FILE *fp);//函数,可以取地址,函数调用,比宏慢
int getchar();// == getc(stdio);
- 文件出错&eof 都返回EOF -1
- 用 int ferror(FILE *fp);
int feof(FILE *fp);
判断读结束原因
FILE中维护 文件结束标志& 出错标志
int ungetc(int c,FILE *fp);//出错返回EOF
- 把字符想流中压栈相当于
- 不会写到文件中,存到缓冲区中
输出putc,fputc,putchar