说明:
在学习UI高级知识之前,将利用最近十来天的时间回顾一下C语言,主要按照《C程序设计(谭浩强版)》来回顾。
整理一些知识点(不是细节,知识个人觉得较重要或易忘的)以及挑一些课后题目或经典习题编写代码练习。
第10章 对文件的输入输出(此部分文字描述较多)
1、几个基础概念
(1)根据数据的组织形式,数据文件可分为ASCII文件和二进制文件
(2)映像文件:数据在内存中以二进制形式存储,如果不加转换地输出到外存,则为二进制文件,可以认为它就是存储在内存的数据的映像。
文本文件:要求在外存上以ASCII代码形式存储,需要在存储前进行转换
(3)文件缓冲区:从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘去。如果从磁盘向计算机读入数据,也一样,缓冲区充满后再逐个将数据送到程序数据区。
(4)文件类型指针(文件指针)
typedef struct {
short level; //缓冲区“满”或“空”的程度
unsigned flags; //文件状态标识
char fd; //文件描述符
unsigned char hold; //如缓冲区无内容不读取字符
short bsize; //缓冲区的大小
unsigned char* buffer; //数据缓冲区的位置
unsigned char* curp; //指针当前的指向
unsigned istemp; //临时文件指示器
short token; //用于有效性检查
}FILE;
不同的编译系统之间的定义大同小异。
2、以一个程序引入文件的各种文件操作方法
#include <stdio.h>
#include <stdlib.h>
//将一个磁盘文件中的信息复制到另一个磁盘文件中,
int main(int argc, const char * argv[]) {
FILE *in,*out; //定义指向FILE类型文件的指针变量
char ch;
char infile[] = "/Users/Zane/Desktop/学习相关/弄潮者/exercise/文件/infile.txt";
char outfile[] = "/Users/Zane/Desktop/学习相关/弄潮者/exercise/文件/outfile.txt";
if ((in = fopen(infile, "r")) == NULL) { //打开文件
printf("无法打开此文件1\n");
exit(0);
}
if ((out = fopen(outfile, "w")) == NULL) {
printf("无法打开此文件2\n");
exit(0);
}
while (!feof(in)) { //如果未遇到输入文件的结束标志
ch = fgetc(in); //从输入文件读入一个字符,暂放在变量ch中
fputc(ch, out); //将ch写道输出文件中
putchar(ch); //将ch显示到屏幕上
}
putchar(10); //显示完全部字符后换行
fclose(in);
fclose(out);
return 0;
}
(1)fopen(文件名,使用文件方式)
返回值:指向文件的指针(文件信息区的起始地址)
文件使用方式 | 含义 | 若指定文件不存在 |
---|---|---|
“r”只读 | 输入,打开已存在文本文件 | 出错 |
“w”只写 | 输出,打开一个文本文件 | 建立新文件 |
“a”追加 | 文本文件尾添加数据 | 出错 |
“rb”只读 | 输入,打开二进制文件 | 出错 |
“wb”只写 | 输出,打开二进制文件 | 建立新文件 |
“ab”追加 | 二进制文件尾添加数据 | 出错 |
“r+”读写 | 读写,打开文本文件 | 出错 |
“w+”读写 | 读写,建立新的文本文件 | 建立新文件 |
“a+”读写 | 读写,打开文本文件 | 出错 |
“rb+”读写 | 读写,打开二进制文件 | 出错 |
“wb+”读写 | 读写,建立新二进制文件 | 建立新文件 |
“ab+”读写 | 读写,打开二进制文件 | 出错 |
注意:
a、若打开出错,fopen会有错误信息,返回NULL,可能是用“r”打开并不存在的文件;磁盘出故障;磁盘已满无法建立新文件等
因此一般会检查打开文件操作是否有错,exit函数作用是关闭所有文件,终止正在执行的程序,待用户检查出错误,修改后重新运行;要包含stdlib.h头文件
b、上述表不是所有的C版本都能用,有些“r+”“w+”“a+”不能用;
c、程序中使用3个标准的流文件——标准输入流stdin,标准输出流stdout,标准出错输出流stderr。
(2)flose(文件指针);成功执行返回0,否则返回EOF(-1)。
撤销文件信息区和文件缓冲区,使文件指针变量不在指向该文件。
如果不关闭文件会丢失数据。之前提到的文件缓冲区概念,不关闭会导致缓冲区的数据丢失。fclose先把缓冲区的数据输出到磁盘文件,然后才撤销文件信息区。
(3)读写字符
函数 | 返回 |
---|---|
fgetc(fp) | 成功返回所读字符,失败返回文件结束标志EOF(-1) |
fputc(ch,fp) | 成功返回输出字符,失败返回文件结束标志EOF(-1) |
(4)feof(fp);
检查文件读写位置标记是否移到文件的末尾,到末尾返回1,否则为0;
(5)读写字符串
函数 | 功能 | 返回值 |
---|---|---|
fgets(str,n,fp) | 读取n-1的字符串存放在str | 成功返回str地址,否则NULL |
fputs(str,fp) | str所指字符串写入文件 | 成功返回0,否则EOF |
说明:fgets读入n-1个字符,然后在最后加一个’\0’
如果在读完n-1个字符之前遇到换行符’\n’或文件结束符EOF,读入结束,但将所遇到的换行符”\n”也作为一个字符读入。
(6)格式化方式读写
函数 | 功能 |
---|---|
fprintf(fp,”%d,%f”,i,f) | 将i和f按一定格式输出到fp指向的文件 |
fscanf(fp,”%d,%f”,&i,&f) | 从fp读取送给i和f |
说明:fscanf:如果磁盘上有字符3,4,5,那么会读取3给i,读取4,5给f。结合代码操作知道就行。
由于输入输出存在ASCII码和二进制之前的相互转换,花费时间较多,因此在内存与磁盘频繁交换数据的时候,不要用。而用fread和fwrite。
(7)二进制方式读写
函数 | 功能 |
---|---|
fread(buffer,size,count,fp) | 将i和f按一定格式输出到fp指向的文件 |
fwrite(buffer,size,count,fp) | 从fp读取送给i和f |
说明:
a、buffer:对fread是存放数据存储区的地址;对fwrite,从此地址开始输出
b、size:要读些的字节数
c、count:读写多少个数据项,每项长度为size
例如fread(f,4,10,fp);
表示从fp所指向的文件读入10个4字节的数据,存储到数组f中
d、fread,fwrite执行成功,返回值为形参count的值(一个整数)
3、随机读写数据文件
(1)文件位置标记(文件标记):系统设置,用来表示“接下来要读写的下一个字符的位置”。下一个!下一个!下一个!重要的事情说三遍!!!
有些教材成为“文件位置指针”,注意此处的指针与C语言中的指针完全不同,因为其不是变量在内存中存储单元的地址。
(2)文件位置标记定位
函数 | 功能 |
---|---|
rewind(fp) | 使文件位置标记重新返回文件的开头,此函数没有返回值 |
fseek(fp,位移量,起始点) | 将文件位置标记离起始点一定位移量的地方 |
ftell(fp) | 测定文件位置标记的当前位置 |
说明:
a、fseek起始点0,1,2分别代表文件开始位置,当前位置,末尾位置
位移量是一起始点为基点,向前!向前!向前移动的字节数。应该是long型,在数字末尾加数字L
因此fseek(fp,-10L,1);
表示文件标记向后退到离当前位置10个字节处
b、ftell返回的是相对于文件开头的位移量,若函数出错,返回-1L
4、文件读写出错检测:调用文件读写函数出错除了函数返回值有放映,也可以用ferror反映。
(1)ferror(fp);返回值为0表示未出错,非零则出错;
注意:同一文件每次调用输入输出函数都会产生新的ferror值函数值,因此调用后要立即检查,否则数据会丢失。同时fopen以后,ferror的初始值是0;
(2)clearerr(fp);使ferror函数值变为0,以便进行下一次的检测。