大家好,我们今天接着来分享文件操作的内容。
我们为什么使用文件呢,使用文件有着什么样的好处呢?
1、使用文件,主要就是为了永久保存,下一次运行可以读取上一次的数据。
2、文件保存数据相当于小型的数据库,存储在本地磁盘中,方便管理和存储数据。
3、可以实现数据共享,多人同时操作一份数据。
那么什么是文件呢?
磁盘上的文件是文件。 但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)
程序文件:包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境
后缀为.exe)。
数据文件:文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。
我今天给大家分享的是数据文件,在以前各章所处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上。其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理的就是磁盘上文件。
看到这里想必大家就会有一个疑问了,文件长什么样子呢?那么我们现在就来看看的文件名。
文件名包含3部分:文件路径+文件名主干+文件后缀
例如:c:\code\test.txt
在此之前我们要知道一个文件指针的概念。缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名 字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统 声明的,取名FILE.不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异。每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节。一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。
例如我们创建一个文件指针变量:
FILE* pf;//文件指针变量
定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变
量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联
的文件,如下图所示:
我们这里定义了三个指针,它们指向的都是与它们相关联的文件。
文件的打开和关闭
文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。
在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指 针和文件的关系。 ANSIC
规定使用fopen函数来打开文件,fclose来关闭文件。
接下来我们就来看看这两个函数的参数:
这里fopen函数的第一个参数为文件名,第二个为打开方式。
//打开文件
FILE * fopen ( const char * filename, const char * mode );
//关闭文件
int fclose ( FILE * stream );
那么我们如何来打开文件呢,有什么打开方式呢?
1.r
以只读方式打开 , 文件必须存在 如果文件存在 , 则 文件打开成功 ; 如果文件不存在 , 返回的 FILE *p 为 NULL ;
这里通过判定 FILE* 类型的返回值是否为 NULL , 可以判断文件是否打开成功:
int main()
{
// 以 r 方式打开文件
FILE *p = fopen("data.txt", "r");
if(p == NULL)
{
printf("File Open Failed !\n");
}else
{
printf("File Open Success !\n");
// 如果打开成功 , 则需要关闭文件
fclose(p);
}
return 0;
}
2.w
以写的方式打开文件 ;
如果文件不存在 , 就创建文件 ; 如果文件存在 , 覆盖原有数据重新写入数据
int main()
{
// 以 w 方式打开文件
FILE* p = fopen("data.txt", "w");
if (p == NULL)
{
perror("fopen");
}
else
{
fputs("hello\n", p);
// 如果打开成功 , 则需要关闭文件
fclose(p);
}
printf("Main End\n");
return 0;
}
我们这里通过fopen运用写的方式打开,那么就会在我们的文件夹中生成一个data.txt的文件,而这里,我们还用到了一个fputs函数,这个函数的作用就是向我们生成的文件中输出我们要输出的值。
3.rb
为了输入数据,打开一个二进制文件、如果文件存在 , 则 文件打开成功 ; 如果文件不存在 , 返回的 FILE *p 为 NULL ;
int main()
{
// 以 rb+ 读写方式 打开 二进制文件
FILE* p = fopen("data.txt", "rb+");
if (p == NULL)
{
perror("fopen");
}
else
{
printf("File Open Success !\n");
fputs("Hello\n", p);
fputs("World\n", p);
// 如果打开成功 , 则需要关闭文件
fclose(p);
}
return 0;
}
这里由于我们并没有文件data.txt,所以我们打开文件失败。
4.wb
以读写方式打开文本文件 , 允许读写 ;
如果文件存在 , 则 文件打开成功 ; 如果文件不存在 , 返回的 FILE *p 为 NULL。
int main()
{
// 以 rw+ 读写方式 打开文件
FILE* p = fopen("data.txt", "wb");
if (p == NULL)
{
perror("fopen");
}
else
{
printf("File Open Success !\n");
fputs("Hello\n", p);
fputs("World\n", p);
// 如果打开成功 , 则需要关闭文件
fclose(p);
}
return 0;
}
打开方式我们就以这几个例子进行讲解。
文件的顺序读写
fgetc():读取一个字符
fputc():写入一个字符
fgets():读取一个字符串
fputs():写入一个字符串
fprintf():写入格式化数据
fscanf():格式化读取数据
fread():读取数据
fwrite():写入数据
第一个参数为我们要写入的数据,第二个参数为我们的文件指针。
int main()
{
FILE* f;
f = fopen("file.txt", "w");
if (f != NULL)
{
fputs("fopen example", f);
fclose(f);
f=NULL;
}
return 0;
}
利用fgetc(),遇到末尾或者错误,会返回EOF,所以以EOF判断
int main()
{
FILE* pf = fopen("file.txt", "r");
if (pf == NULL)
{
perror("fwrite ERROR");
return 1;
}
int ch = 0;
while ((ch = fgetc(pf)) != EOF)
{
printf("%c ", ch);
}
// 关闭
fclose(pf);
pf = NULL;
return 0;
}
所以我们通过fgetc函数读取我们文件中的字符,一次读取一个字符。
int main()
{
FILE* pf = fopen("file.txt", "w");
if (pf == NULL)
{
perror("fwrite ERROR");
return 1;
}
char ch = 'a';
for (; ch <= 'z'; ch++)
{
fputc(ch, pf);
}
// 读取
//fopen(pf);
// 关闭
fclose(pf);
return 0;
}
我们这里就将26个字母写入了文件之中。
在这里我们同样只以这几个例子来讲解。
fseek
origin:文件指针当前位置,offset为偏移量。SEEK_SET为指针最开始的位置,SEEK_CUP为当前的位置,SEEK_END为末尾的位置。
int main()
{
// 打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
// 随机写
// 随机读
fseek(pf, 3, SEEK_CUR);
int ch = fgetc(pf);
printf("%c\n", ch);
// 关闭文件
fclose(pf);
pf = NULL;
return 0;
}
所以我们从最开始的位置偏移三个位置的得到d。
ftell
该函数的作用是返回文件指针相对于起始位置的偏移量
int main()
{
// 打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
// 随机写
// 随机读
fseek(pf, 0, SEEK_END);
int len = ftell(pf);
fclose(pf);
printf("test.txt 的总大小 = %d 字节\n", len);
// 关闭文件
fclose(pf);
pf = NULL;
return 0;
}
rewind
让文件指针的位置回到文件的起始位置
int main()
{
// 打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
// 随机写
// 随机读
fseek(pf, 3, SEEK_CUR);
int ch = fgetc(pf);
printf("%c\n", ch);
rewind(pf);
int len = ftell(pf);
fclose(pf);
printf("test.txt 的总大小 = %d 字节\n", len);
// 关闭文件
fclose(pf);
pf = NULL;
return 0;
}
因为我们的test.txt文件中的数据为abcde,我们从开始的位置偏移三个位置,得到d,我们在rewind将文件指针回到初始位置,在ftell得到偏移量,所以偏移量为0。
我们今天的分享就到这里了,我们下次见。