【C复习】04:文件操作
创始人
2025-05-30 04:22:41

文件操作


OVERVIEW

  • 文件操作
      • 一、打开与关闭文件
        • 1.fopen
        • 2.fclose
      • 二、顺序读写数据文件
        • 1.向文件读写字符
        • 2.向文件读写字符串
        • 3.格式化方式读写文件
        • 4.二进制方式读写文件
      • 三、随机读写数据文件
        • 1.文件位置标记
        • 2.随机读写
        • 3.读写错误检测

所谓文件一般都是指存储在外部介质上数据的集合,输入输出时数据传输的过程,即数据流。

根据数据的组织形式,数据文件可以分为ASCII文件和二进制文件,

  • 数据在内存中是以二进制存储的,如果不加转换的输出到外存,可以认为其就是存储在内存数据中的映像,称之为映像文件
  • 如果要求在外存上以ACSII代码形式存储,则需要再存储前进行转换,称之为本文文件

数据在磁盘上的存储方式:字符文件一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以用二进制形式存储。

每个被使用的文件都在内存中开辟一个相应的文件信息区,用来存放文件的相关信息(文件的名字、文件状态以及文件当前位置),这些信息是保存在一个结构体变量中的,FILE:

typedef struct {short level;//缓冲区满or空unsigned flags;//文件状态标志char fd;//文件描述符unsigned char hold;//如缓冲区无内容不读取字符short bsize;//缓冲区的大小unsigned char *buffer;//数据缓冲区的位置unsigned char *curp;//指针当前的指向unsigned istemp;//临时文件指示器short token;//用于有效性检查
} FILE;

每一个FILE类型变量对应一个文件的信息区,将指向文件信息区的指针称为文件指针。

注:指向文件的指针变量并不是指向外部介质上的数据文件的开头,而是指向内存中的文件信息区的开头

一、打开与关闭文件

1.fopen

所谓打开文件是指为文件建立相应的信息区(存放有关文件信息)与文件缓冲区(暂时存放输入输出数据)。

//常用的打开文件的方式
FILE *fp;
if ((fp = fopen("file.txt", "r")) == NULL) {printf("can not open this file\n");exit(0);
}

image-20230317211703764

程序中可以使用3个标准的流文件:标准输入stdin、标准输出stdout、标准错误输出stderr

标准输入流是从终端的输入、标准输出流是向终端的输出、标准错误输出流是程序出错将错误信息发送到终端。

程序开始运行时系统自动打开这3个标准流文件,程序编写者直接使用即可。

2.fclose

关闭文件就是撤销文件信息区与文件缓冲区,使文件指着不再指向该文件。

如果不关闭文件将会丢失数据,因为向文件写入数据时是先将数据输入到缓冲区,待缓冲区满之后才会写入磁盘(缓冲区数据丢失)。

fclose(fp);

二、顺序读写数据文件

在顺序读写中,先写入的数据存放在文件中前面的位置,后写入的数据存放在文件中后面的位置。

1.向文件读写字符

image-20230317215643717

  • 用fgetc函数从键盘逐个读入字符 然后用fputc函数将数据写入磁盘文件:
#include
#includeint main() {FILE *fp;char ch;char filename[10];printf("please enter a filename:");scanf("%s", filename);if ((fp = fopen(filename, "w")) == NULL) {printf("can not open this file\n");exit(0);}ch = getchar();//用于接收最后输入的回车符printf("please enter a char array end with a '#':");ch = getchar();while (ch != '#') {fputc(ch, fp);//向磁盘文件写入一个字符ch = getchar();}fclose(fp);return 0;
}

成功通过fputc函数向test.txt文件中逐个字符写入,文件操作成功。

  • 将一个磁盘文件中的信息复制到另一个磁盘文件中:
#include
#includeint main() {FILE *inputfp, *outputfp;char ch;char srcFileName[20], destFileName[20];printf("enter the input file name:");scanf("%s", srcFileName);printf("enter the output file name:");scanf("%s", destFileName);if ((inputfp = fopen(srcFileName, "r")) == NULL) {//打开输入文件printf("can not open this src file!\n");exit(0);}if ((outputfp = fopen(destFileName, "w")) == NULL) {//打开输出文件printf("can not open this dest file!\n");exit(0);}while (!feof(inputfp)) {//feof函数用于检测文件读写是否到达末尾ch = fgetc(inputfp);//src字符读取fputc(ch, outputfp);//dest字符写入}fclose(inputfp);fclose(outputfp);return 0;
}

2.向文件读写字符串

image-20230317233447063

注:fgets和fputs函数功能类似于gets和puts函数,只是gets和puts以终端为读写对象,而fgets和fputs以指定的文件为读写对象。

  • 从键盘读入若干个字符串,对它们按字母大小顺序排序,然后把排好序的字符串送到磁盘文件中进行保存。
#include
#include
#includeint main() {FILE *fp;char str[3][20];char temp[20];int n = 3;printf("please enter your strings:\n");for (int i = 0; i < n; ++i) gets(str[i]);//从标准输入设备中获取字符串 并用str[i]指针对其指向//1.对字符串进行排序(直接选择排序)for (int i = 0; i < n - 1; ++i) {int max = i;for (int j = i + 1; j < n; ++j) {//寻找i及其之后的字符串中最大的字符串 并将其赋值给maxif (strcmp(str[max], str[j]) > 0) max = j;}if (max != i) {//将最大的字符串放在有序的位置strcpy(temp, str[i]);strcpy(str[i], str[max]);strcpy(str[max], temp);}}//2.打开文件if ((fp = fopen("string.txt", "w")) == NULL) {printf("can not open the file!\n");exit(0);}//3.写入数据for (int i = 0; i < n; ++i) {fputs(str[i], fp);fputs("\n", fp);}return 0;
}
  • string.txt中将数据读会到字符串数组中,并将其打印在屏幕上:
#include
#includeint main() {FILE *fp;char str[3][50];//1.打开文件if ((fp = fopen("string.txt", "r")) == NULL) {printf("can not open the file\n");exit(0);}//2.将文件中的数据读入数组int index = 0;while (fgets(str[index], 50, fp) != NULL) index++;//3.将数组中的数据进行打印for (int i = 0; i < 3; ++i) printf("%s", str[i]);fclose(fp);return 0;
}

3.格式化方式读写文件

注:fprintf和fscanf与printf和scanf的区别是其读写对象不是终端而是文件。

  • fprintf(文件指针, 格式字符串, 输出列表);
  • fscanf(文件指针, 格式字符串, 输入列表);

用fprintf和fscanf函数对磁盘文件进行读写使用方便,但是由于需要进行ACSII码与二进制形式之间的转换,花费时间较多。

因此在内存与磁盘进行频繁交换数据的情况下,最好不用。

而用fread与fwrite函数进行二进制的读写。

4.二进制方式读写文件

C语言允许使用fread函数从文件中读一个数据块,用fwrite函数向文件中写入一个数据块(读写以二进制形式进行)。

在向磁盘写入数据时,直接将内存中的数据原封不动的复制到磁盘文件上。

  • fread(buffer, size, count, fp);
  • fwrite(buffer, size, count, fp);
  • buffer:地址
  • size:要读写的字节数
  • count:要读写多少个数据项(每个数据项长度为size)
#include#define SIZE 5struct Student {char name[20];int num;int age;char addr[50];
};struct Student stu[SIZE];void bwrite() {FILE *fp;if ((fp = fopen("stu.txt", "wb")) == NULL) {printf("can not open the file\n");return;}for (int i = 0; i < SIZE; ++i) {if (fwrite(&stu[i], sizeof(struct Student), 1, fp) != 1) {printf("file write error\n");}}fclose(fp);
}void bread() {FILE *fp;if ((fp = fopen("stu.txt", "rb")) == NULL) {printf("can not open the file\n");return;}for (int i = 0; i < SIZE; ++i) {fread(&stu[i], sizeof(struct Student), 1, fp);}fclose(fp);
}int main() {printf("please enter data of the student:\n");for (int i = 0; i < SIZE; ++i) scanf("%s %d %d %s", stu[i].name, &stu[i].num, &stu[i].age, stu[i].addr);bwrite();printf("current data of the student:\n");bread();for (int i = 0; i < SIZE; ++i) printf("%-10s%4d%4d%10s\n", stu[i].name, stu[i].num, stu[i].age, stu[i].addr);return 0;
}

image-20230318114524521

三、随机读写数据文件

随机访问不是按数据在文件中的物理位置次序进行读写的,而是可以对任何位置上的数据进行访问,这种方法比顺序访问效率高很多。

1.文件位置标记

为了对读写进行控制,系统为每个文件设置了一个文件读写位置标记(文件位置标记),

image-20230318115135599

可以根据读写需要,人为的移动文件位置标记的位置,即随机读写。

  • rewind:作用是使文件位置标记重新指向文件开头,无返回值。

    FILE *fp1, *fp2;
    fp1 = fopen("src.txt", "r");
    fp2 = fopen("dest.txt", "w");
    while (!feof(fp1)) putchar(getc(fp1));//将文件内容输出到屏幕
    rewind(fp1);
    while (!feof(fp1)) putc(getc(fp1), fp2);//将文件内容拷贝到dest.txt
    fclose(fp1);
    fclose(fp2);
    
  • fseek:用于改变文件位置标记,fseek一般用于二进制文件,fseek(文件指针, 位移量, 起始点);
    image-20230318115849431

  • ftell:作用是得到流式文件中文件位置标记的当前位置,用相对于文件开头的位移量来表示。出错返回-1

2.随机读写

  • 在磁盘上存有10个学生的数据,要求利用文件随机读写将1、3、5、7、9个学生的数据输出到屏幕上。
FILE *fp;
if ((fp = fopen("stu.txt", "rb")) == NULL) {printf("can not open the file\n");exit(0);
}
for (int i = 0; i < SIZE; i += 2) {fseek(fp, i * sizeof(struct Student), 0);//移动文件位置标记fread(&stu[i], sizeof(struct Student), 1, fp);//读取一个数据块到结构体变量printf("%-10s%4d%4d%10s\n", stu[i].name, stu[i].num, stu[i].age, stu[i].addr);
}
fclose(fp);

3.读写错误检测

  • ferror(fp)

在调用各种输入输出函数(putc、getc、fread、fwrite)时如果出现错误,除了函数返回值有所反映外,还可以使用ferror函数检查。

如果返回值为0表示没有读写错误,如果返回非零值表示读写出错。

注:在调用1个输出输出函数后,需要立即检查ferror函数的返回值,否则错误信息会丢失。

  • clearerr(fp)

clearerr函数的作用是使文件错误标志文件结束标志置为0,

在输入输出函数出现错误ferror值为一个非零值时,应立即调用clearerror(fp),以便在进行下一次检查。

相关内容

热门资讯

联动云租一天多少钱(联动云租一... 本篇文章极速百科给大家谈谈联动云租一天多少钱,以及联动云租一天怎么划算对应的知识点,希望对各位有所帮...
飞机托运收费(飞机托运收费多少... 本篇文章极速百科给大家谈谈飞机托运收费,以及飞机托运收费多少钱一公斤对应的知识点,希望对各位有所帮助...
挡泥板(挡泥板是什么意思) 挡... 本篇文章极速百科给大家谈谈挡泥板,以及挡泥板是什么意思对应的知识点,希望对各位有所帮助,不要忘了收藏...
滴滴专车官网(滴滴专车司机网站... 今天给各位分享滴滴专车官网的知识,其中也会对滴滴专车司机网站进行解释,如果能碰巧解决你现在面临的问题...
路特斯跑车(路特斯跑车多少钱一... 今天给各位分享路特斯跑车的知识,其中也会对路特斯跑车多少钱一辆2023款进行解释,如果能碰巧解决你现...
丰田致享新车报价(丰田致享20... 今天给各位分享丰田致享新车报价的知识,其中也会对丰田致享2021款报价进行解释,如果能碰巧解决你现在...
聊城到潍坊的汽车(聊城到潍坊的... 本篇文章极速百科给大家谈谈聊城到潍坊的汽车,以及聊城到潍坊的汽车票价多少对应的知识点,希望对各位有所...
没有身份证怎么买票(没有身份证... 今天给各位分享没有身份证怎么买票的知识,其中也会对没有身份证怎么买票进行解释,如果能碰巧解决你现在面...
2018科目三灯光详细表(20... 本篇文章极速百科给大家谈谈2018科目三灯光详细表,以及2018科目三最新模拟灯光考试20组不重复完...
五菱之光v(五菱之光v和五菱之... 今天给各位分享五菱之光v的知识,其中也会对五菱之光v和五菱之光有什么区别进行解释,如果能碰巧解决你现...
摩托车怠速(摩托车怠速多少转正... 今天给各位分享摩托车怠速的知识,其中也会对摩托车怠速多少转正常进行解释,如果能碰巧解决你现在面临的问...
武汉到西安(武汉到西安火车时刻... 今天给各位分享武汉到西安的知识,其中也会对武汉到西安火车时刻表查询进行解释,如果能碰巧解决你现在面临...
五菱之光v图片(五菱之光v新车... 今天给各位分享五菱之光v图片的知识,其中也会对五菱之光v新车报价进行解释,如果能碰巧解决你现在面临的...
郑州到重庆火车(郑州到重庆火车... 本篇文章极速百科给大家谈谈郑州到重庆火车,以及郑州到重庆火车多少钱一张对应的知识点,希望对各位有所帮...
学生证优惠区间(学生证优惠区间... 今天给各位分享学生证优惠区间的知识,其中也会对学生证优惠区间没有盖章进行解释,如果能碰巧解决你现在面...
武汉到合肥(武汉到合肥多少公里... 今天给各位分享武汉到合肥的知识,其中也会对武汉到合肥多少公里进行解释,如果能碰巧解决你现在面临的问题...
软座座位分布图(k8412软座... 本篇文章极速百科给大家谈谈软座座位分布图,以及k8412软座座位分布图对应的知识点,希望对各位有所帮...
长安逸动dt(长安逸动dt空调... 本篇文章极速百科给大家谈谈长安逸动dt,以及长安逸动dt空调滤芯拆卸教程对应的知识点,希望对各位有所...
西安到达州(西安到达州火车时刻... 本篇文章极速百科给大家谈谈西安到达州,以及西安到达州火车时刻表查询对应的知识点,希望对各位有所帮助,...
野马蝰蛇(野马蝰蛇gt500图... 本篇文章极速百科给大家谈谈野马蝰蛇,以及野马蝰蛇gt500图片对应的知识点,希望对各位有所帮助,不要...
高速obu是什么意思(收费站o... 今天给各位分享高速obu是什么意思的知识,其中也会对收费站obu是什么意思进行解释,如果能碰巧解决你...
西安北站在哪(西安北站在哪进站... 今天给各位分享西安北站在哪的知识,其中也会对西安北站在哪进站进行解释,如果能碰巧解决你现在面临的问题...
汽车搭电一次多少钱(汽车搭电大... 今天给各位分享汽车搭电一次多少钱的知识,其中也会对汽车搭电大概多少钱进行解释,如果能碰巧解决你现在面...
宝马跑车敞篷价格(宝马跑车敞篷... 本篇文章极速百科给大家谈谈宝马跑车敞篷价格,以及宝马跑车敞篷价格图片对应的知识点,希望对各位有所帮助...
cbr650r(cbr650r... 本篇文章极速百科给大家谈谈cbr650r,以及cbr650r座高对应的知识点,希望对各位有所帮助,不...
在哪买机票最便宜(在哪买机票最... 今天给各位分享在哪买机票最便宜的知识,其中也会对在哪买机票最便宜票进行解释,如果能碰巧解决你现在面临...
etc办理点(etc办理点节假... 今天给各位分享etc办理点的知识,其中也会对etc办理点节假日休息吗进行解释,如果能碰巧解决你现在面...
宝马1181报价及图片(宝马1... 今天给各位分享宝马1181报价及图片的知识,其中也会对宝马1181报价及图片及价格进行解释,如果能碰...
限行处罚扣分吗(限行被扣分吗)... 本篇文章极速百科给大家谈谈限行处罚扣分吗,以及限行被扣分吗对应的知识点,希望对各位有所帮助,不要忘了...
车车(车车车念什么) 车车 车... 今天给各位分享车车的知识,其中也会对车车车念什么进行解释,如果能碰巧解决你现在面临的问题,别忘了关注...