io: input output
io 设备:
输入设备: 键盘终端 ===》默认标准输入
输出设备: 显示器终端 ===》默认标准输出
标准输入设备:会阻塞等待;
io 分层:
文件io: ===>基于操作系统对外提供的一组系统调用接口函数
===> man 2 xxx 查看
===>安全性 高效率 同一接口
标准io: ===>基于文件io的一组对外提供功能的c库函数
====>man 3 xxx 查看
====>可移植 带缓存 高效率
标准io:===>stdio.h ===>/usr/include/stdio.h
1、标准io缓存机制====>行缓存 满缓存 不缓存
行缓存:标准输出设备在输出的时候遇到’\n’会自动刷新
输出缓存区数据。
输出对象: 标准输出设备 == stdout
输出方式: 标准io库函数 == printf fprintf
输出效果: 有'\n'刷新,没有则缓存。
缓存区在程序正常结束的时候会自动刷新。
满缓存: 当缓存区数据填满的时候,自动刷新缓存区。
默认的标准输出满缓存是 1024 字节
普通文件的默认满缓存是 4096 字节
如果需要在非满缓存时候刷新缓存区可以使用
fflush()函数强制刷新缓存区;
不缓存: 在输出的时候,没有缓存区缓存数据直接输出。
int fprintf(FILE *stream, const char *format, …);
功能:函数可以将格式化的数据输出到指定的stream流对象上。
参数:stream 文件流指针,是一个文件对象。
== stdin =>默认的标准输入流对象 不能在fprintf使用
== stdout=>默认的标准输出流对象 等价 printf
== stderr===>默认的错误输出流对象 会不缓存输出
== fp ===>fp 对应的文件流对象
format ... 完全类似printf的操作使用。
返回值:成功 0
失败 -1;
操作的对象: stderr
操作的方式: fprintf
操作的结果: 不缓存直接输出
2、标准io文件流指针 ===》FILE * stream = xxxx;
int * pa = &a;
文件流分类:
ascii 流 == 文本流 ==》人可直接识别并处理
二进制流 ===》人不可直接识别需要再次加工处理
FILE 类型:===》操作框架类似读书
找到并打开文件 ===》读写文件 ==》 关闭归还文件
linux 设计哲学之一: 一切皆为文件
linux 文件标准操作框架:
fopen()===> fgetc()/fputc() ==>fclose()
=====>标准io库函数
3、标准io库函数
标准io操作文件统一框架:
打开文件 ====》读写文件(定位文件) ====》关闭文件
fopen() fgetc()/fputc() fclose()
freopen() fgets()/fputs()
fdopen() fread()/fwrite()
fscanf()/fprintf()
fseek()/rewind()/ftell()
3.1 fopen ==>fdopen===>freopen
FILE *fopen(const char *path, const char *mode);
功能:函数可以指定的mode方式打开指定路径+名称的文件;
参数:path 要打开的文件路径+名称;
mode 要打开的文件读写方式,可以有如下6种模式
r 只读 文件必须存在
r+ 读写 文件必须存在
w 只写 创建 清空
w+ 读写 创建 清空
a 只写 创建 追加
a+ 读写 创建 追加
以上6种方式任选其一。
返回值:成功 FILE * 文件流指针,指向打开的文件
失败 NULL;
//fopen代码
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE * fp = fopen("./abc","r");//只读方式打开文件
if(NULL == fp)//判断文件是否为空
{
perror("fopen error");
return -1;
}
printf("fopen return fp = %p \n",fp);
fclose(fp);//关闭文件
return 0;
}
3.2 要验证文件是否可以读写,必须查看文件读写方式:
单字符读写: fgetc()/fputc()
字符串读写: fgets()/fputs()
二进制读写: fread()/fwrite()
格式化读写: fscanf()/fprintf()
3.2.1 单字符读写:
int fgetc(FILE *stream); ///读操作
功能:函数可以从指定的文件流中获取一个字符并返回。
参数:stream 文件流指针
返回值:成功 获取到的文件中字符
文件结尾 EOF == -1
失败 -1
判断文件结尾的函数:
int feof(FILE *stream);
功能:该函数可以用来检测是否到达文件结尾,如果
已经是文件结尾则该函数返回真,否则返回假。
参数:stream 要检测的目标文件流指针
返回值:结尾 真
非结尾 假
注意:该函数一定要在读操作之后再判断。
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE * fp = fopen("./abc","r");
if(NULL == fp)
{
perror("fopen error");
return -1;
}
printf("fopen return fp = %p \n",fp);
int c = fgetc(fp);
if(feof(fp))
{
printf("file end \n");
goto end;
}
if(EOF == c)
{
printf(" error");
}
else
{
printf("fgetc c = %c \n",c);
}
end:
fclose(fp);
return 0;
}
int fputc(int c, FILE *stream); ///写操作
功能:该函数可以将指定的一个字符写入到目标文件流中
参数:c 要写入文件的字符
stream 要写入的文件流
返回值:成功 写入的文件字符
失败 -1;
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE * fp = fopen("./abc","r+");
if(NULL == fp)
{
perror("fopen error");
return -1;
}
printf("fopen return fp = %p \n",fp);
int c = 'x';
int ret = fputc(c,fp);
if(ret < 0)
{
perror("fputc error");
return -1;
}
else
{
printf("fputc return ret = %d \n",ret);
}
fclose(fp);
return 0;
}
3、关闭文件流
int fclose(FILE *fp);
功能:关闭指定的已经打开的文件流
参数:fp 要关闭的文件流对象
返回值:成功 0
失败 -1
注意:同一个文件不能反复关闭。
一个打开的文件必须关闭否则内存泄漏。
fgetc() ===> getchar()
===>getchar() 默认从标准输入获取一个字符
===>fgetc() 从指定的文件流获取一个字符
===>stdin == 标准输入流,fgetc(stream)
====>getchar() == fgetc(stdin);
====>fgetc() 可以从标准输入(stdin)获取数据
也可以从指定的文件流(fp)获取数据
适用范围比getchar() 大。
====>getchar() == getc() == fgetc();
fputc() ===> putchar()
===>putchar() 默认从标准输出打印一个字符
===>fputc() 向指定的文件流输出一个字符
===>stdout == 标准输出流 == fputc(c,stdout)
putchar()== putc() == fputc()