1.文件操作
1.1 概述:
我们进行的所有操作都是在计算机内存中进行的,并且我们所操作的数据也是存放在计算机内存中的,一旦我们退出了程序,内存空间就会被释放并回收,而这个过程中我们所操作的所有的数据也将不复存在。如此,我们无法将数据真正保留下来,只能在每次运行程序时重新进行输入,重新录入信息,使用起来极为不便。
1.1.1 为什么使用文件:
我们希望将数据保留在本地,只有当我们进行删除操作时,才将对应的数据删除掉,即尝试实现数据的持久化。而我们实现数据持久化的方式一般有两种:使用数据库或将数据存放至本地磁盘中。
目前还没有接触到数据库的知识,于是我们便通过学习文件操作,来将我们的数据存放至我们计算机的本地硬盘中,从而实现数据的持久化。
1.1.2 什么是文件:
我们通常所说的文件,一般是指存放在我们计算机本地硬盘上的文件。但是在我们的程序设计中(根据文件功能分类),指的是程序文件与数据文件两种文件。
①.程序文件:
程序文件主要包括源程序文件、目标文件和可执行程序文件。
源程序文件(后缀为 .c)
目标文件( Windows 环境下后缀为 .obj)
可执行程序文件( Windows 环境下后缀为 .exe)
②.数据文件:
数据文件的内容不一定是程序,而是程序运行过程中所进行读写的数据,比如程序运行中需要从中读取的数据,或者程序运行完毕所输出的文件。
今天所讨论的,正是数据文件的相关操作
在前面所有内容的学习中,我们所有的输入输出,其操作对象都是终端,均为从键盘读取输入内容,并将处理结果输出致我们的计算据显示器上进行反馈。而今天我们的目的则是将数据信息输入至我们的本地磁盘上,当我们想要对数据进行操作时,便从本地硬盘进行读取。
③.文件名:
文件和我们人类有自己的名字一样,也需要有一个文件标识符,文件名的存在就是为了便于我们进行识别和引用。
而一个文件的文件名由三部分组成:文件路径 + 文件名主干 + 文件后缀
以文件名“ c:\code\test.txt ”为例:
文件路径为“ c:\code\ ”,表示文件存放在硬盘 C 盘下的 code 文件夹内。
文件名主干为“ test ”,表示该文件的文件名为 test。
文件后缀为“ .txt ”,表示该文件的文件类型为文本文件。
2. 文件顺序读写:
2.1 文件的打开和关闭:
我们在使用或操作我们的文件之前,首先需要在我们的程序中及将其打开
①.文件指针:
首先需要了解一下文件指针这个概念,这是因为不光是文件的打开与关闭,包括后面我们在对我们的文件进行操作时,也都是通过文件指针实现的。
在缓冲文件系统中,最关键的一个概念就是“ 文件类型指针 ”,即我们通常所说的“ 文件指针 ”。并且我们要知道,我们使用的每一个文件都在内存中开辟了相应的文件信息区,用于存放该文件的相关信息,并且这些信息都保存在一个结构体变量中。
并且这样的结构体类型是有系统声明的,取名为 FILE。
例如在 Visual Studio 的头文件stdio.h中(非自定义结构体类型)就有该类型的声明:
struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int _file; int _charbuf; int _bufsiz; char *_tmpfname; }; typedef struct _iobuf FILE;
使用不同的 C 语言编译器,FILE 类型中所包含的信息可能不完全相同,但是都大同小异。每当我们打开一个本地文件时,系统就会依据我们打开的文件的情况自动创建出一个 FILE 结构的变量,并填充该结构内的信息。而这个由系统创建出来并填充的 FILE 结构变量,就是通过一个 FILE 类型文件指针类进行调用和维护的。
FILE* p; //定义一个文件指针p
像这样,我们就能创建出一个文件指针,而接下来就可以使这个文件指针 p 指向某个文件信息区(FILE 类型的结构体变量),并通过该文件信息区中所保存的信息来访问本地硬盘内的文件了。通过使用文件指针就可以找到与其相关联的文件了。
②.文件的打开与关闭:
应在读写文件之前打开文件,并在文件读写结束后关闭文件。同时ANSI C规定,使用 fopen 函数(file open)来打开文件,用 fclose 函数(file open)来关闭文件。
什么是ANSI C、ISO C、C89、C90标准?
随着C语言使用得越来越广泛,出现了许多新问题,人们日益强烈地要求对C语言进行标准化。1983年,美国国家标准协会(ANSI)组成了一个委员会,X3J11,为了创立C的一套标准。经过漫长而艰苦的过程,该标准于1989年完成,这个版本的语言经常被称作ANSI C,或有时称为C89(为了区别C99)在1990年,ANSI C标准(带有一些小改动)被美国国家标准协会(ANSI)采纳为ISO/IEC 9899:1990。这个版本有时候称为C90或者ISO C。综上,ANSI C、ISO C、C89、C90其实是同一种标准。
open 函数的使用方式为:
FILE* p = fopen(const char* filename, const char* mod);
1.其中“ const char* filename ”指文件名(是字符串,文件名即文件标识符)。
2.其中“ const char* mod ”指文件打开模式(也是字符串,后面会列出)
int main() { //打开文件: FILE* p = fopen("test.txt", "r"); //以"r",即只读模式打开文件c:\code\test.txt //默认路径为.c文件同目录下 if (p == NULL) //判断文件打开是否成功 { perror("FILEOPEN"); //打开失败打印错误原因并退出 return 1; } printf("success\n"); return 0; }
fclose 函数的使用方式为:
fopen(FILE* strname); • 1
“ FILE* strname ”指的是指向期望关闭文件的文件指针。
因为我们在打开文件时没有特意注明路径,则默认路径为 .c 文件的同目录下。为了验证我们代码的正确性,我们在该目录下创建“ test.c ”文件用于代码测试:
int main() { //打开文件: FILE* p = fopen("test.txt", "r"); //以"r",即只读模式打开文件c:\code\test.txt if (p == NULL) //判断文件打开是否成功 { perror("FILEOPEN"); //打开失败打印错误原因并退出 return 1; } printf("open success\n"); //验证文件是否成功打开 fclose(p); p = NULL; if (p == NULL) { printf("close success\n"); //验证文件是否成功关闭 } return 0; }
③.文件打开模式:
2.2.文件的顺序读写:
这其中较为常用的就是 fputc 函数与 fgetc 函数,我们一般就通过这两个函数来实现对文件内容的顺序读写。
这两个函数的使用方式为:
fputc(const char charname, FILE* strname); fget(FILE* strname);
首先文本文件 test.txt 中的内容为空,没有内容
接下来我们使用“ 写 ”模式打开该文件,并在判断非空后使用 fputc 函数来进行顺序写入:
int main() { FILE* p = fopen("test.txt", "w"); //文件打开模式为“写” if (p == NULL) { perror("FILEOPEN"); return 1; } char ch = 'a'; for (ch = 'a'; ch <= 'z'; ch++) { fputc(ch, p); //使用 fputc 函数顺序写入小写字符a~z } fclose(p); p = NULL; return 0; }
我们等待程序编译运行并完成数据写入后关闭程序,这时我们来到本地文件中查看硬盘中本地文件的数据写入情况:
我们看到本地文件中的内容已经实现了数据的顺序写入。