流I/O总览
文件I/O的一般情况
1.程序必须为同时处于活动状态的每个文件声明一个指针变量,其类型为FILE*。这个指针指向FILE结构,当它处于活动状态时由流使用。
2.流通过调用fopen函数打开,为了打开一个流,必须指定需要访问的文件或设备以及它们的访问方式(例如:读,写,既读又写)。fopen和操作系统验证文件或者设备确实存在并初始化FILE结构。
3.根据指定的方式对文件进行操作。
4.调用fclose函数关闭流。关闭流可以防止与它相关联的文件被再次访问,保证任何存储于缓冲区的数据被正确读写的文件,并且释放FILE结构使它可以用于另外的文件。
标准的I/O流更简单,因为它们不需要关闭或者打开。
I/O函数以三种基本的形式处理数据:单个字符,文本行和二进制数据。对于每种形式都有一组特定的函数对它们进行处理。
执行字符、文本行和二进制数据I/O的函数:
数据类型 |
输入 |
输出 |
描述 |
字符 |
getchar |
putchar |
读取(写入)单个字符 |
文本行 |
gets/scanf |
puts/printf |
文本行未格式化的输入(输出)/格式化的输入(输出) |
二进制数据 |
fread |
fwrite |
读取(写入)二进制数据 |
输入/输出函数家族:
家族名 |
目的 |
可用于所有流 |
只用于stdin和stdout |
内存中的字符串 |
getchar |
字符输入 |
fgetc, getc |
getchar |
① |
putchar |
字符输出 |
fputc, putc |
putchar |
① |
gets |
文本行输入 |
fgets |
gets |
② |
puts |
文本行输出 |
fputs |
puts |
② |
scanf |
格式化输入 |
fscanf |
scanf |
sscanf |
printf |
格式化输出 |
fprintf |
printf |
sprintf |
①对指针使用下标引用或间接访问操作从内存获得一个字符(或向内存写入一个字符)。
②使用strcpy函数从内存读取文本行(或向内存写入文本行)。
打开流
fopen函数打开一个特定的文件,并把一个流和这个文件相关联。原型如下:
FILE *fopen(const char *name , const char *mode);
name是要打开的文件或设备名,fopen把文件名作为一个字符串。
mode由rwatb+六个字符组合而成, r表示读, w表示写, a表示追加(Append) ,在文件末尾追加数据使文件的尺寸增大。 t表示文本文件, b表示二进制文件 。
如果省略t和b, rwa+四个字符有以下6种合法的组合 :
"r" |
只读,文件必须已存在 |
"w" |
只写,如果文件不存在则创建,如果文件已存在则把文件长度截断(Truncate) 为0字节再重新写,也就是替换掉原来的文件内容 |
"a" |
只能在文件末尾追加数据,如果文件不存在则创建。 |
"r+" |
允许读和写,文件必须已存在。 |
"w+" |
允许读和写,如果文件不存在则创建,如果文件已存在则把文件长度截断为0字节再重新写。 |
"a+" |
允许读和追加数据,如果文件不存在则创建。 |
在mode中添加“a+”表示该文件打开用于更新,并且流既允许读又允许写。但是,如果已经读了一些数据,在写入数据之前要调用一个文件定位函数(fseek、fsetpos、rewind)。如果在写入数据之后又想读取,必须调用fflush函数或文件定位函数之一。
如果fopen函数执行成功,返回一个指向FILE结构的指针,代表这个新创建的流。如果执行失败,返回一个NULL指针。应始终检测fopen的返回值。
freopen函数用于打开(或重新打开)一个特定的文件流,原型如下:
FILE* freopen(const char* filename, const char* name, FILE* stream);
最后一个参数是需要打开的流,然后用指定的文件和模式重新打开这个流。如果打开失败,函数返回NULL指针,如果成功,则返回第三个参数值。
关闭流
int fclose(FILE* f);
对于输出流,fclose函数在文件关闭之前刷新缓冲区。如果执行成功,fclose返回零值,否则返回EOF。
打开文件操作完之后一定要记得关闭。如果不调用fclose,在进程退出时系统会自动关闭文件,但是不能因此就忽略fclose调用,如果写一个长年累月运行的程序(比如网络服务器程序),打开的文件都不关闭,堆积得越来越多,就会占用越来越多的系统资源。