C语言中,I/O操作可以简单地看作是从程序移进或移出字节,这种搬运的过程便称为流(stream)。程序只需要关心是否正确地输出了字节数据,以及是否正确地输入了要读取字节数据,特定I/O设备的细节对程序员是隐藏的。 c++必包含的头文件 iostream 意味就是输入输出流
首先使用标准库函数进行文件相关操作
- 程序为同时处于活动状态的每个文件声明一个指针变量,其类型为FILE*。这个指针指向这个FILE结构,当它处于活动状态时由流使用。
- 流通过fopen函数打开。为了打开一个流,我们必须指定需要访问的文件或设备以及他们的访问方式(读、写、或者读写)。Fopen和操作系统验证文件或者设备是否存在并初始化FILE。
- 根据需要对文件进行读写操作。
- 最后调用fclose函数关闭流。关闭一个流可以防止与它相关的文件被再次访问,保证任何存储于缓冲区中的数据被正确写入到文件中,并且释放FILE结构。
I/O函数以三种基本的形式处理数据:单个字符、文本行和二进制数据。
家族名 | 目的 | 可用于所有流 | 只用于stdin和stdout |
getchar | 字符输入 | fgetc、getc | getchar |
putchar | 字符输出 | fputc、putc | putchar |
gets | 文本行输入 | fgets | gets |
puts | 文本行输出 | fputs | puts |
scanf | 格式化输入 | fscanf | scanf |
printf | 格式化输出 | fprintf | printf |
文件指针
文件指针也可以理解为代指打开的文件。这个指针的类型为FILE类型。该类型定义在stdio.h头文件中。
由于c标准并未制定FILE的成员,所以不同编译器有不同的定义(QT与vs略有不同 请注意)
VS下的定义
struct _iobuf {
char *_ptr; //文件输入的下一个位置
int _cnt; //剩余多少字符未被读取
char *_base; //指基础位置(应该是文件的其始位置)
int _flag; //文件标志
int _file; //文件的有效性验证
int _charbuf; //检查缓冲区状况,如果无缓冲区则不读取
int _bufsiz; //文件的大小
char *_tmpfname; //临时文件名
};
typedef struct _iobuf FILE;
文件打开(open)
文件的打开操作表示将给用户指定的文件在内存分配一个FILE结构区,并将该结构的指针返回给用户程序,以后用户程序就可用此FILE指针来实现对指定文件的存取操作了。当使用打开函数时,必须给出文件名、文件操作方式(读、写或读写)。
FILE * fopen(const char * filename, const char * mode);
功能:打开文件
参数:
filename:需要打开的文件名,根据需要加上路径
mode:打开文件的权限设置
返回值:
成功:文件指针
失败:NULL
具体的打开文件权限也在这里简单的写一下
“r” 打开,只读,文件必须已经存在。
“w” 只写,如果文件不存在则创建,如果文件已存在则把文件长度截断(Truncate)为0字节。再重新写,也就是替换掉原来的文件内容文件指针指到头。
“a” 只能在文件末尾追加数据,如果文件不存在则创建
“rb” 打开一个二进制文件,只读
“wb” 打开一个二进制文件,只写
“ab" 打开一个二进制文件,追加
“r+” 允许读和写,文件必须已存在
“w+” 允许读和写,如果文件不存在则创建,如果文件已存在则把文件长度截断为0字节再重新写 。
“a+” 允许读和追加数据,如果文件不存在则创建
“rb+” 以读/写方式打开一个二进制文件
“wb+” 以读/写方式建立一个新的二进制文件
“ab+” 以读/写方式打开一个二进制文件进行追加
写一个DEMO
void test(){
FILE *fp = NULL;
// "\\"这样的路径形式,只能在windows使用
// "/"这样的路径形式,windows和linux平台下都可用,建议使用这种
// 路径可以是相对路径,也可是绝对路径
fp = fopen("../test", "w");
//fp = fopen("..\\test", "w");
if (fp == NULL) //返回空,说明打开失败
{
//perror()是标准出错打印函数,能打印调用库函数出错原因
perror("open");
return -1;
}
}
必须注意的两个点,一是路径,如果不在工程文件夹内,建议使用绝对路径
二是应该检查fopen的返回值!如何函数失败,它会返回一个NULL值。如果程序不检查错误,这个NULL指针就会传给后续的I/O函数。它们将对这个指针执行间接访问,并将失败.
文件读写
按照字符读写文件:fgetc(), fputc()
按照行读写文件:fputs(), fgets()
按照块读写文件:fread(), fwirte()
按照格式化读写文件:fprintf(), fscanf()
按照随机位置读写文件:fseek(), ftell(), rewind()
注意一下读文件结尾的一个函数
int feof(FILE * stream);
功能:检测是否读取到了文件结尾
参数:
stream:文件指针
返回值:
非0值:已经到文件结尾
0:没有到文件结尾
文件的关闭
文件操作完成后,如果程序没有结束,必须要用fclose()函数进行关闭,这是因为对打开的文件进行写入时,若文件缓冲区的空间未被写入的内容填满,这些内容不会写到打开的文件中。只有对打开的文件进行关闭操作时,停留在文件缓冲区的内容才能写到该文件中去,从而使文件完整。再者一旦关闭了文件,该文件对应的FILE结构将被释放,从而使关闭的文件得到保护,因为这时对该文件的存取操作将不会进行。文件的关闭也意味着释放了该文件的缓冲区。
int fclose(FILE * stream);
功能:关闭先前fopen()打开的文件。此动作让缓冲区的数据写入文件中,并释放系统所提供的文件资源。
参数:
stream:文件指针
返回值:
成功:0
失败:-1