1:流的定向决定了读取的是多字节还是单字节的流,当一个流最初被创建的时候,并没有被定向,若在一个未定向的流上使用一个多字节的IO函数,则将该流定向设置为宽定向的,反之在未定向的流上使用一个单字节的IO函数,则将该流的定向设置为字节定向的。
2:有两个函数可以改变流的定向,分别是freopen和fwide
3:int fwide(FILE *fp, int mode);
若流是宽定向则返回正值,若流是字符定向则返回负值,未定向则返回0
4:mode:正:试图使指定的流是宽定向
负:试图使指定的流是字节定向的
0:不设置流的定向,但是返回标示该流的定向的值
5:fwide并不改变已经定向的流,且无错误返回状态,所以唯一可依靠的是在调用fwide之前先清除errno,从fwide返回前检查errno的值。
6:标准IO库提供缓冲的目的是尽可能减少read和write的次数,并对每个IO流自动进行缓冲管理,避免了应用程序需要考虑这一点所带来的麻烦。
7:三种缓冲策略:
1:全缓冲,标准IO缓冲区满了之后才进行实际IO操作,对于驻留在磁盘上的文件都进行全缓冲操作,在一个流上第一次进行IO操作的时候,相关IO函数通常调用malloc来获取使用的缓冲区
flush:在IO库方面,flush意味着将缓冲区的内容写到磁盘上,在终端驱动方面,则表示丢弃已存储在缓冲区中的数据。
2:行缓冲:在输入和输出中遇到换行时标准IO库执行IO操作,只有在写了一行之后才进行实际的IO操作,当涉及到一个终端时(如标准输入输出),通常使用行缓冲
有两点需要注意,标准IO库用来收集每一行的缓冲区的长度是固定的,所以只要填满了缓冲区,即使还没有换行,也要进行IO操作。
3:不带缓冲,标准IO不对字符进行缓冲,例如标准IO函数fputs写15个字符到不带缓冲的流上,则该函数可能立刻调用write系统调用将字符写到关联的打开的文件上。
标准错误流是不带缓冲的,可以允许错误信息立刻显式出来。
有以下标准可供参考:
当且仅当输入和输出不涉及交互式设备的时候,他们才是全缓冲的。
标准错误是不带缓冲的,若涉及到终端设备的其他流,则他们是行缓冲的,否则是全缓冲的。
8:更改缓冲类型函数族:
void setbuf(FILE *restrict fp, char *restrict buf)
int setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size)
成功返回0
对于函数setbuf,可以打开或者关闭缓冲机制,为了带缓冲进行IO,buf必须指向一个长度为BUFSIZ的缓冲区,通常定义在stdio.h中,通常在此之后该流就是全缓冲的,但若该流和一个终端设备相关,某些设备也可以将其设置为行缓冲,若关闭缓冲,只需将buf设置为NULL.
对于setvbuf则可以更加精确的设置缓冲类型,是通过Mode参数来实现的,
_IOFBF
_IOLBF
_IONBF
若指定一个不带缓冲的流,则忽略buf和size参数,若指定行缓冲或者全缓冲,则需给buf和size一个缓冲区和长度,如果流是带缓冲的,而buf是NULL,则标准IO将自动为该流分配适当的缓冲区,通常有BUFSIZ所指定的值。
若缓冲区是在函数内部分配的自动变量,在函数返回前一定要关闭该流,实际缓冲区可存放的字节数是要少于size的,因为有一些管理信息在其中。
9:强制冲洗一个流:
int fflush(FILE *fp);成功返回0,失败返回EOF,若fp是NULL,将导致所有的输出流被冲洗
10:打开流
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)
获取一个现有的文件描述符,并使一个标准IO流与该描述符相结合,通常用于创建管道和网络通信通道函数返回的描述符。因为这些特殊的类型文件不能用IO标准fopen函数打开,所以必须调用设备专用函数获得一个文件描述符,然后使用fdopen使一个标准IO流与该描述符关联。
11:关闭一个打开的流
int fclose(FILE *fp)关闭之前先冲洗缓冲区中的数据,丢弃缓冲区中的任何输入,若标准IO已经为该流自动分配了一个缓冲区,则释放该缓冲区,当一个进程终止时,所有带未写缓冲数据的标准IO流都会被冲洗,所有打开的标准IO流都会关闭。
12:读写操作,
1:每次一个字符的IO,一次读或写一个字符,若流是带缓冲的,则标准IO函数会处理所有缓冲
2:每次一行的IO,若一次读写一行,则使用fgets和fputs,每行用一个换行终止,若调用fgets应该说明能处理的最大的行长
3:直接IO,fread,fwrite.通常用于从二进制文件中每次读或者写一个结构。
13:一次读取一个字符的函数
int getc(FILE *fp)
int fgetc(FILE *fp)
int getchar(void)
14:输出函数
int putc(int c. FILE *fp)
int fputc(int c,FILE *FP)
int putchar(int c)
15:每一行的IO
char *fgets(char *restrict buf, int n, FILE *restrict fp)
char *gets(char *buf)
gets从标准输入读,fgets从指定的流读。
16:二进制IO
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)
EX:
struct{
short count;
long total;
char name[NAMESIZE];
}item;
if(fwrite(&item, sizeof(item),1,fp) != 1)
err_sys(.......);
返回读写的对象数。
17:对于读到出错或者文件尾端,则此数字可能少于nobj,此情况下可以用ferror或者feof来判断哪一种情况,对于写的话若返回值少于nobj则出错。
18:格式化流
int fprintf(FILE *restrict fp, const char *restrict format, ......);
19:printf与scanf函数族
20:函数fileno,获取一个打开文件的文件描述符。