三个标准输入输出
以下三个输入输出就像已经打开的文件流一样,可以直接拿来用
l 标准输入: /dev/stdin或FILENO_STDIN,shell代号0,对应键盘;
l 标准输出: /dev/stdout或FILENO_STDOUT,shell代号1,对应显示器;
l 标准错误输出: /dev/stderr或FILENO_STDERR,shell代号2,对应显示器。
三种缓冲缓冲用于减少对系统函数read/write的调用次数,提高读写效率
非缓冲IO:每次修改时都要进行一次系统IO调用,系统IO将修改内容写入到文件中缓冲IO:把文件的内容读到一块内存区域,每次修改都在内存区域中操作,最终修改完成后再调用系统IO写入到文件中,那块内存区域称为缓冲区
1.全缓冲:在缓冲区写满时输出到指定的输出端.比如对磁盘上的文件进行读写通常是全缓冲的.
2.行缓冲:在遇到'\n'时输出到指定的输出端.比如标准输入和标准输出就是行缓冲,回车后就会进行相应的I/O操作.
3.无缓冲:有什么就输出什么.比如标准错误输出,出错时立即显示出来.
可用fflush立即输出,不管缓冲区是否达到输出标准设置缓冲方式的函数有两个,分别为setbuf,setvbuf
打开、关闭
1.FILE *fopen(const char *restrict pathname, const char *restrict type)第一个参数为文件的路径,第二个参数为打开的方式,有读/写/添加/重写等选项
2.int fclose(FILE *fp)关闭打开的文件流,释放内存
读写
1.每次读写一个字符
getc/fgetc/getchar
putc/fputc/putchar
2.每次读写一行
fgets/gets
fputs/puts
3.每次读写一个对象
这种读写方式也称为二进制方式,由我们自己设定一次读几个字节(不是字符) ,以文本方式打开时通常是乱码
l size_t fread(void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp)
参数含义:从fp读取,读取的内容写到ptr指向的内存,每次读取size个字符,一共读nobj次
l size_t fwrite(const void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp)
通常用于读取格式固定的文件,比如有个文件的内容如下:
0000,0001,0002,0003,0004, ... ... ... 9995,9996,9997,9998,9999,
从0000-9999的所有四位数,每个对象由4个数字组成,之间用逗号隔开那么我们读的时候就可以一次读5个字符
定位
用于在打开的文件中跳到指定位置进行读写
l fseek:跳转到指定的文件位置
l ftell:获取文件指针当前所在位置
l rewind:回到文件头
格式化
写:
l printf:格式化数据写到标准输出
l fprintf:格式化数据写到指定的流
l sprintf/snprintf:格式化数据写到指定的字符数组
读: scanf/fscanf/sscanf
例子1
缓冲直观感受,新建一个test.txt,向里面写入两行字符,在fflush前后各输出一次文件内容。因为文件是全缓冲,所以第一次没有内容输出,第二次fflush强制刷新缓冲区输出内容.另外fclose(fp)也会调用fflush刷新缓冲区.
#include #include
#define MAXLINE 1024char outbuf[MAXLINE];
//输出文件内容void showcontent(){
puts("----- start showcontent -------");
FILE *fp;
if((fp=fopen("./test.txt","r")) ==NULL){
perror("fopen error");
exit(-1);
}
while(fgets(outbuf,MAXLINE,fp) !=NULL){
puts(outbuf);
}
puts("----- end showcontent -------");
}
//w+模式打开,每次打开文件都会擦除原有内容再写入,如果文件不存在就创建void fullbuf(){
FILE *fp;
if((fp=fopen("test.txt","w+")) ==NULL){
perror("fopen error");
exit(-1);
}
fputs("This is fullbuf.",fp);
fputs("all content output at a time.",fp);
puts("before fflush");
showcontent();
fflush(fp);
puts("after fflush");
showcontent();
fclose(fp);
}
int main(){
fullbuf();
return 0;
}
例子2
在一些简单的单机游戏中,游戏角色的属性是用二进制方式保存的.如名称用char[length]来保存,等级用int来保存,经验值用unsigned int来保存,将这些属性结合在一起形成一个struct,在玩家退出游戏时调用fwrite保存起来,等玩家再次登录时调用fread读取属性。
下面的例子很简单,将五个people结构写入文件然后再读取出来
#include #include
struct people{
char name[10];
int age;
};
void readstruct(){
struct people man[10];
FILE *fp;
if((fp=fopen("./test.txt","r")) == NULL){
perror("fopen error");
exit(-1);
}
fread(man,sizeof(struct people),5,fp);
int i;
for(i=0;i<5;++i)
printf("%d. name=%s, age=%d\n",i+1,man[i].name,man[i].age);
fclose(fp);
}
void writestruct(){
struct people man[10];
int i;//输入并回车: first 1 second 2 third 3 fourth 4 fifth 5
for(i=0;i<5;++i){
scanf("%s",&man[i].name);
scanf("%d",&man[i].age);
}
FILE *fp;
if((fp=fopen("./test.txt","w+")) == NULL){
perror("fopen error");
exit(-1);
}
fwrite(man,sizeof(struct people),5,fp);
fclose(fp);
}
int main(int argc,char *argv[]){
writestruct();
readstruct();
return 0;