标准IO
为什么使用标准IO?
系统IO在不同操作系统下的API接口不一致:
- Linux:
open,read,write,close... - Windows:
winopen,winread...
C/C++语言标准委员会统一了文件操作接口 --> 标准IO
- 支持所有操作系统
- 提供统一的文件操作函数
- 通过IO流(文件)抽象文件操作
文件类型:
- 文本文件:
- 无组织、无格式,以字符ASCII解析
- 如:
.cpp,.c,.txt,.cs,.html,.java,.py...
- 二进制文件:
- 有特定格式,需按格式解析
- 如:
.exe,.out,.apk,.jpg,.mp4,.doc,.xls...
文件描述结构:
标准库用FILE结构体描述文件,包含两个缓冲区:
- 读缓冲区 (
char *in) - 写缓冲区 (
char *out)
操作流程:应用程序 -> 标准IO库 -> 操作系统IO -> 操作系统内核 -> 硬件
效率优势:
- 系统IO:读1字节需从硬盘取1字节
- 标准IO:读1字节从硬盘取整块数据放入缓冲区
- 缓冲类型:
类型 同步条件 默认大小 行缓冲 缓冲区满/遇到 \n/程序正常退出1024字节 全缓冲 缓冲区满 4096字节 无缓冲 有1字节即同步 1字节
- 缓冲类型:
标准IO流
程序自动打开三个标准IO流:
- 标准输入流:
FILE *stdin- 指向输入设备(键盘)
- 如:
scanf
- 标准输出流:
FILE *stdout- 指向输出设备(终端)
- 如:
printf
- 标准出错流:
FILE *stderr- 指向错误输出设备(终端)
- 如:
perror
标准IO API接口
打开/关闭文件流
c
FILE *fopen(const char *filename, const char *modes);
/*
@描述:
打开文件流
@filename:
文件名(含路径)
@modes:
"r" : 只读,流定位到文件开头
"r+" : 读写,流定位到文件开头
"w" : 只写,截断文件或创建新文件
"w+" : 读写,文件不存在则创建,存在则截断
"a" : 追加写入,文件不存在则创建
"a+" : 读写追加,写入时定位到文件末尾
@return:
成功返回FILE*指针,失败返回NULL(errno被设置)
*/
int fclose(FILE *stream);
/*
@描述:
关闭文件流
@stream:
文件流指针
@return:
成功返回0,失败返回EOF(errno被设置)
*/读写操作
单字节读写
c
// 读取单字节
int fgetc(FILE *stream);
/*
@描述:
从文件流读取一个字符
@stream:
文件流指针
@return:
成功返回字符ASCII码,失败返回EOF
*/
// 写入单字节
int fputc(int c, FILE *stream);
/*
@描述:
写入字符到文件流
@c:
字符ASCII码
@stream:
文件流指针
@return:
成功返回字符ASCII码,失败返回EOF
*/行读写
c
// 读取一行
char *fgets(char *s, int size, FILE *stream);
/*
@描述:
从文件流读取一行
@s:
存储字符串的空间
@size:
最大读取字节数(包含结尾\0)
@stream:
文件流指针
@return:
成功返回s地址,失败返回NULL
*/
// 写入字符串
int fputs(const char *s, FILE *stream);
/*
@描述:
写入字符串到文件流
@s:
待写入字符串
@stream:
文件流指针
@return:
成功返回非负数,失败返回EOF
*/注意:
fputs与puts区别:
fputs可指定输出流,无自动换行puts固定输出到stdout,自动添加\n
直接读写
c
// 块读取
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
/*
@描述:
从文件流读取数据块
@ptr:
存储数据的内存地址
@size:
单个元素大小
@nmemb:
元素个数
@stream:
文件流指针
@return:
成功返回实际读取的元素个数
*/
// 块写入
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
/*
@描述:
写入数据块到文件流
@ptr:
待写入数据地址
@size:
单个元素大小
@nmemb:
元素个数
@stream:
文件流指针
@return:
成功返回实际写入的元素个数
*/缓冲区控制
c
// 强制同步缓冲区
int fflush(FILE *stream);
/*
@描述:
强制同步缓冲区数据到硬件
@stream:
文件流指针(NULL表示刷新所有流)
@return:
成功返回0,失败返回EOF
*/
// 设置缓冲区策略
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
/*
@描述:
设置缓冲区类型和大小
@stream:
文件流指针
@buf:
用户提供的缓冲区(需长期有效)
@mode:
_IONBF(无缓冲)
_IOLBF(行缓冲)
_IOFBF(全缓冲)
@size:
缓冲区大小
@return:
成功返回0
*/文件定位
c
// 设置光标位置
int fseek(FILE *stream, long offset, int whence);
/*
@描述:
移动文件流光标
@stream:
文件流指针
@offset:
偏移量(正数向后,负数向前)
@whence:
SEEK_SET(文件开头)
SEEK_CUR(当前位置)
SEEK_END(文件末尾)
@return:
成功返回0,失败返回-1
*/
// 获取光标位置
long ftell(FILE *stream);
/*
@描述:
获取光标到文件头的字节数
@stream:
文件流指针
@return:
成功返回字节数,失败返回-1
*/
// 重置光标到文件头
void rewind(FILE *stream);
/*
@描述:
重置光标到文件开头
@stream:
文件流指针
*/错误处理
c
// 清除错误标志
void clearerr(FILE *stream);
// 检测文件结束
int feof(FILE *stream);
/*
@return:
文件结束返回非0,否则返回0
*/
// 检测文件错误
int ferror(FILE *stream);
/*
@return:
出错返回非0,否则返回0
*/格式化I/O
格式化输入
c
// 从文件流格式化输入
int fscanf(FILE *stream, const char *format, ...);
// 从字符串格式化输入
int sscanf(const char *str, const char *format, ...);格式化输出
c
// 输出到文件流
int fprintf(FILE *stream, const char *format, ...);
// 输出到字符串
int sprintf(char *str, const char *format, ...);格式化字符串规则:
- 普通字符:必须精确匹配输入
- 格式化字符:
%d,%s,%c,%f...- 转义字符:
\n,\t,\x89...
C++文件操作
cpp
#include <fstream>
// 文件写入
ofstream;
// 文件读取
ifstream;
// 文件读写
fstream;
// 打开文件
void open(const char *filename, ios::openmode mode);打开模式:
ios::in:读模式ios::out:写模式ios::ate:初始位置在文件尾ios::app:追加模式ios::trunc:存在则截断ios::binary:二进制模式
作业
- 封装标准IO操作为C++类
- 完成目录拷贝作业
