文章目录
一、简单介绍
1. 文件是什么?
文件通常是在磁盘或固态硬盘上的一段已命名的存储区,是指存放在外部存储介质(可以是磁盘、光盘、磁带等)上的数据集合。C把文件看作是一系列连续的字节,每个字节都能被单独读取。
2. 文件的操作流程
打开(建立)文件–>读写文件–>关闭文件
3. 如何操作文件
C语言是通过文件指针变量的操作来实现对文件的具体访问。
- 先了解一下 FILE结构体类型:
要调用一个文件,一般需要该文件的一些信息,例如:文件当前的读写位置、与该文件对应的内存缓冲区的地址、缓冲区中未被处理的字符串、文件操作方式等。缓冲文件系统会为每一个文件系统开辟一个“文件信息区”,包含在头文件stdio.h中,被定义为FILE类型数据。注意 FILE 应为大写,是由系统定义的一个结构体,该结构体中包含了文件名、文件使用方式、当前位置等信息。
- 文件指针(指向FILE类型结构体的指针变量):
例:FILE *fp;
fp是一个指向FILE类型结构体的指针变量,可以使fp指向某一个文件类型的结构体变量,从而通过该结构体变量中的文件信息访问该文件,也就是说通过该文件指针变量能够找到与它相关的文件。
二、对文件的操作
对文件的操作都是通过标准函数来实现的。
1. 文件的打开与关闭
1.1打开文件
所谓打开文件,实际上是建立文件的各种有关信息,并使文件指针指向该文件,以便进行其他操作。
-
函数:fopen();
-
函数原型:FILE * fopen(char *filename, char * mode);
-
参数:
filename–这是 C 字符串,包含了要打开的文件名称。
mode–这是 C 字符串,包含了文件访问模式。 -
功能:使用给定的模式 mode 打开filename 所指向的文件。文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回 NULL。
-
打开方式:
如果希望接收 fopen() 的返回值,就需要定义一个FILE 类型的指针。
举例:
-
打开一个和可执行文件在相同路径下(文件夹相同)的文本文件,只需要写文件名即可。
FILE *fp;
fp = fopen(“test.txt”, ”r”); -
打开一个D盘下code文件夹下的文本文件test.txt。 (数据文件与程序文件分别存放在不同的文件夹,就必指定完整的路径和文件名)
FILE *fp;
fp = fopen(“d:\\code\\test.txt”, ”rt”);
或
FILE * fp;
fp = fopen(“d:/code/test.txt”, ”rt”);
以上两种方法属于嵌入式文件方法,即文件名及其所在路径已在程序中设定。 -
还有一种由键盘输入所要打开的文件名及其路径。
char filename[40];
gets(filename);
fp = fopen(filename, “r”);
!!!!由以上例子可以看出,在打开一个文件时,通知给编译系统有三个信息
-
需要打开的文件名。
-
使用文件的方式(读、写等)
-
用哪个指针变量指向被打开的文件。
1.2 关闭文件
在程序中,当对一个文件的操作使用完毕后,应将其关闭,断开文件指针与该文件之间的联系,防止文件遭到其他操作的破坏。使用 fclose() 函数将指定的文件关闭,并将FILE文件指针的相关资源及所占用的缓冲区归还给系统。
- 函数原型:int fclose( FILE *fp );
- 功能:将文件指针fp所指向的文件关闭。
- 返回值:如果文件成功关闭,则该方法返回零。如果失败,则返回 EOF。
2. 文件的读写
文件的读写是通过读写函数实现的。
根据文件的读写方式不同,文件可分为文件的顺序读写和文件的随机读写。
- 顺序读写是指将文件从头到尾逐个数据读出或写入,即读写文件子还能从头开始,顺序读取各个数据。
- 随机读写是可移动文件内部的位置指针到需要读写的位置,再进行读写。
位置指针:
在文件内部有一个位置指针,用来指向当前读写到的位置,也就是读写到第几个字节。在文件打开时,该指针总是指向文件的第一个字节。
文件内部的位置指针与C语言中的指针不是一回事。位置指针仅仅是一个标志,表示文件读写到的位置,也就是读写到第几个字节,它不表示地址文件每读写一次,位置指针就会移动一次,它不需要你在程序中定义和赋值,而是由系统自动设置,对用户是隐藏的。
2.1 文件的顺序读写
首先看看所要了解的函数:
单字符读写函数:fgetc 和 fputc
字符串读写函数:fgets 和 fputs
格式化读写函数:fscanf 和 fprintf
数据块读写函数:fread 和 fwrite
2.1.1 单字符读写函数(fgetc fputc)
字符读写函数是以字符(字节)为单位的读写函数,每次可以从文件读出或向文件写入一个字符。
字符读函数fgetc():
- 函数原型:int fgetc(FILE *fp);
- 功能:读取文件指针fp目前所指文件位置中的字符,读取完毕,文件指针自动往后移一个字符位置,若文件指针已经到文件结尾,返回-1.
字符写函数fputc():
- 函数原型:int fputc(char ch, FILE *fp);
- 功能:将字符ch写入文件指针fp所指向的文件位置,成功时返回字符的asc码,失败时返回EOF(在stdio.h中,符号常量EOF的值等于-1)。
举例:
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE *fp;
char filename[40];
char ch;
int i;
printf("输入文件名:\n");
gets(filename);
fp = fopen(filename, "a+"); //读写打开文件,允许读,或在文件末尾写数据。
if(fp == NULL) {
printf("\n打开文件失败\n");
exit(0);
}
ch = getchar();
while (ch != '\n') {
fputc(ch, fp);
ch = getchar();
}
// ch = getchar();
// fputc(ch, fp); //字符写
fclose(fp); //关闭文件
fp = fopen(filename, "r+"); //打开文件 ,允许读写
if(fp == NULL) {
printf("\n打开文件失败\n");
exit(0);
}
while((ch = fgetc(fp)) != EOF) { //字符读
printf("%c ", ch);
}
fclose(fp); //关闭文件
return 0;
}
2.1.2 字符串读写函数(fgets fputs)
读字符串函数fgets() :
- 函数原型:char *fgets(char *str, int n, FILE *fp);
- 功能:在文件指针fp所指文件位置读取n个字符并放入str字符数组中,如果读不到字符串返回NULL。
写字符串函数 fputs() :
- 函数原型:int fputs(char *str, FILE *fp);
- 功能:将字符串str写入文件指针fp所指的文件位置,写入数据成功时返回非0值,写入失败时返回EOF。(str可以是字符串常量也可以是字符数组名或指针变量)
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE *fp;
char filename[40];
char str[10];
int i;
printf("输入文件名:\n");
gets(filename);
fp = fopen(filename, "a+"); //读写打开文件,允许读,或在文件末尾写数据。
if(fp == NULL) {
printf("\n打开文件失败\n");
exit(0);
}
gets(str);
fputs(str, fp);
fclose(fp);
fp = fopen(filename, "r+");
if(fp == NULL) {
printf("\n打开文件失败\n");
exit(0);
}
while(fgets(str, 10, fp) != NULL) {
printf("%s", str);
}
fclose(fp);
2.1.3格式化字符串读写函数(fscanf fprintf):
格式化字符串读函数fscanf():
-
函数原型:int fscanf(FILE *fp, “格式化字符串”,【输入项地址表】);
-
功能:将文件指针fp所指向的文件中按照格式字符串指定的格式将文件中的数据送到输入项地址表中,若读取数据成功会返回所读取数据的个数,并将数据按照指定格式存入内存中的变量或数组中,文件指针自动向下移动;若读取失败,返回0。
格式化字符串写函数fprintf():
-
函数原型:int fprintf(FILE *fp, “格式化字符串”,【输入项地址表】);
-
功能:将输出项表中的变量值按照格式字符串指定的格式输出到文件指针fp所指向的文件位置。
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE *fp;
char filename[40];
char name[20];
int age;
int i;
printf("输入文件名:\n");
gets(filename);
fp = fopen(filename, "a+"); //读写打开文件,允许读,或在文件末尾写数据。
if(fp == NULL) {
printf("\n打开文件失败\n");
exit(0);
}
scanf("%s %d", name, &age);
fprintf(fp, "%s %d", name, age); //写格式化字符串
fclose(fp); //关闭文件
fp = fopen(filename, "r+"); //打开文件 ,允许读写
if(fp == NULL) {
printf("\n打开文件失败\n");
exit(0);
}
while((fscanf(fp, "%s %d", name, &age) != EOF)) { //读格式化字符串
printf("%s %d ", name, age);
}
fclose(fp); //关闭文件
}
2.1.4 数据块读写函数(fread fwrite):
数据块读函数fread():
- 函数原型:int fread(void *buffer, int size, int count, FILE *fp);
- 功能:从文件指针fp所指向的文件的当前位置开始,一次读入size个字节,重复count次,并将读到的数据存到buffer开始的内存区中,同时将读写位置指针后移size*count次。该函数的返回值是实际读取的count值。
- 参数:
buffer: 是一个指针,在fread函数中,它表示存放读入数据的首地址;在fwrite函数中,它表示要输出的数据在内存中的首地址。
Size: 表示数据块的字节数
Count: 表示要读取的数据块数
数据块写函数fwrite():
-
函数原型: int fwrite(void *buffer,
int size, int count, FILE *fp); -
功能:从buffer所指向的内存区开始,一次输入size个字节,重复count次,并将输入的数据存入到fp说指向的文件中,同时将读写位置指针后移size*count次。
-
代码:
#include<stdio.h>
#include<stdlib.h>
struct stu {
char name[20];
int age;
};
int main() {
char filename[40];
FILE *fp;
printf("输入文件名\n");
gets(filename);
fp = fopen(filename, "a+");
if(fp == NULL) {
printf("\n打开文件失败\n");
exit(0);
}
struct stu student[100];
int n, i;
scanf("%d", &n);
for(i = 0; i < n; i++) {
printf("输入第%d个学生信息\n", i+1);
printf("\n姓名:");
scanf("%s", student[i].name );
printf("\n年龄:");
scanf("%d", &student[i].age );
fwrite(&student[i], sizeof(struct stu), 1, fp);
}
fclose(fp);
fp = fopen(filename, "r+");
printf("\n数据如下\n");
i = 0;
while(fread(&student[i], sizeof(struct stu), 1, fp) != NULL) {
printf("%s %d\n",student[i].name ,student[i].age );
i++;
}
fclose(fp);
}
2.2 文件的随机读写
2.2.1rewind()函数
-
函数原型:void rewind(FILE *fp);
-
功能:将文件内部的位置指针移到文件的开始位置。
2.2.2 fseek()函数
-
函数原型:int fseek(FILE *fp, long offset, int whence);
-
功能:文件指针由whence地址移到offset的地址。
2.2.3 ftell()函数
-
函数原型:long int ftell(FILE *stream);
-
功能:返回给定流 stream 的当前文件位置。
2.2.4 putw函数
- 函数原型:int putw(int w, FILE *fp);
- 功能:对磁盘文件写一个字(整数),返回输出的整数,如果出错,则返回EOF
2.2.5 getw函数
-
函数原型:int getw(FILE *fp)
-
功能:从fp所指向文件读取下一个字(整数)。返回输入的整数。如果文件结束或者出错返回-1。