C语言---14文件操作---01文件内容的顺序读写
文中的源码都在这里哦!!!
文中的源码都在这里哦!!!
一、文件的基本概念
一个文件通常是磁盘上一段命名的存储区
磁盘文件(通常用的文件):指一组相关数据的有序集合,通常存储在外部介质(如磁盘)上,使用时才调入内存
设备文件(与硬件有关的文件):在操作系统中把每一个与主机相连的输入、输出设备看作是一个文件,把它们的输入、输出等同于对磁盘文件的读和写。例如:键盘(标准输入文件)、屏幕(标准输出文件)
以下说的是磁盘文件
(一)磁盘文件的存取过程
磁盘文件,一般保存在硬盘、光盘、U盘等掉电不丢失的磁盘设备中,在需要时调入内存
在内存中对文件进行编辑处理后,保存到磁盘中(内存只是文件的处理区,不是存储区)
程序与磁盘之间交互,不是立即完成,系统或程序可根据需要设置缓冲区,以提高存取效率,延长磁盘寿命(在缓冲区进行暂时存储,直到存储的数据量达到一定的数量,不然存储一次打开一次磁盘,会缩短磁盘寿命)
(二)文件分类(重要)
1、物理上
所有的磁盘文件都是二进制存储,以字节为单位进行顺序存储(空间是连续的)
2、逻辑上
程序文件:有后缀名,主要用于存储程序代码
数据文件:程序运行时读写的数据
数据文件可分为ASCII文件(文本文件)和二进制文件——C语言可识别的文件
文本文件
基于字符编码,常见编码有ASCII、UNICODE等,一般可以使用文本编辑器直接打开
例如:数5678以ASCII存储形式为
ASCII码:00110101 00110110 00110111 00111000
是每个字符的ASCII码值
效率低,需要查表,但便于查看
二进制文件
基于值编码,根据应用指定某个值的意思
把内存中的数据按其在内存中的存储形式原样输出到磁盘上
例如:5678的存储形式为
进制码:0001 0110 0010 1110
读取效率很高,但是解译很麻烦,查看麻烦
3、两者的对比
文本文件 | 二进制文件 | |
---|---|---|
译码 | 编码基于字符定长,译码容易些 | 编码是变长的,译码难一些(不同的二进制文件格式,有不同的译码方式) |
空间利用率 | 任何一个符号至少需要一个字节 | 用一个比特来代表一个意思(位操作) |
可读性 | 通用的记事本工具就几乎可以浏览所有文本文件 | 需要一个具体的文件解码器 |
二、文件操作
C语言中不能直接操作文件,需要借助库函数对文件进行操作
基本流程
在使用文件前要调用打开函数将文件打开,得到文件指针fp
然后调用各种有关函数,利用fp对文件进行具体处理(读或写)
在文件用完时,及时调用关闭函数来关闭文件
C语言中所有的文件操作都围绕文件指针完成(只有通过文件指针,我们才能知道自己操作的是哪个文件),所以操作文件前必须定义一个文件指针指向我们将要操作的文件
(一)文件指针
文件指针:指向文件的指针,可以指向文件的内存地址
格式:FILE * 指针变量标识符
// 由于文件类型已经在stdio.h头文件中有声明了,所以我们不需要另外声明,直接使用就行了FILE *fp = NULL;
FILE为大写,需要包含头文件<stdio.h>
FILE是系统使用typedef定义出来的有关文件信息的一种结构体类型,FILE结构体中含有文件名、文件状态和文件当前位置等信息(不需要关心)
c语言中有三个特殊的文件指针无需定义,打开可直接使用(在后续说明中会提到!!!)
stdin:标准输入。默认为当前终端(键盘),使用的scanf、getchar函数默认从此终端获得数据
stdout:标准输出。默认为当前终端(屏幕),使用的printf、puts函数默认输出信息到此终端
stderr:标准出错。默认为当前终端(屏幕),当我们程序出错或者使用perror函数时信息打印在此终端
(二)打开与关闭文件
任何文件使用之前必须打开,使用后必须关闭
1、fopen打开一个文件
格式:fp = fopen(文件名,文件打开方式)
返回值:返回的是文件的起始地址,执行不成功返回NULL(需要在打开之后判断是否打开成功)
文件名:要操作文件的名字,可包含路径
文件路径 + 文件名主干 + 文件后缀
文件的路径可以唯一标识文件的位置
绝对路径:从根目录(盘符)开始的文件路径 + 文件名 + 文件扩展名(文件类型)
相对路径:相对于当前目录,从当前目录开始访问到某一文件的路径
打开方式:读、写、二进制、文本(与文件的存储方式无关,与操作系统有关)
r:以只读方式打开文件。文件不存在返回NULL;文件存在返回文件指针,进行后续的读操作
w:以只写方式打开文件。文件不存在以指定文件名创建此文件;文件存在则清空文件内容,进行写操作;文件打不开,返回NULL
a:以追加方式打开文件。文件不存在,以指定文件名创建此文件(同w);若文件存在,从文件的结尾处进行写操作
+:可读可写
b:以二进制的方式打开文件
t:以文本的方式打开文件(省略!!!)
- 不是很重要,了解一下就行
- 在windows平台下,当读取文件的时候,系统会将所有的"\r\n"转换成"\n";当写入文件的时候,系统会将"\n"转换成"\r\n"写入
- 在Unix/Linux平台下,“文本”与“二进制”模式没有区别。\r\n作为两个字符原样输入输出
打开方式的组合形式
模 式 |
功 能 |
r或rb |
以只读方式打开一个文本文件(不创建文件) |
w或wb |
以写方式打开文件(使文件长度截断为0字节,创建一个文件) |
a或ab |
以添加方式打开文件,即在末尾添加内容,当文件不存在时,创建文件用于写 |
r+或rb+ |
以可读、可写的方式打开文件(不创建新文件) |
w+或wb+ |
以可读、可写的方式打开文件 (使文件长度为0字节,创建一个文件) |
a+或ab+ |
以添加方式打开文件,打开文件并在末尾更改文件(如果文件不存在,则创建文件) |
顺序读写文件:文件指针会从文件指针当前位置顺序读写文件,打开文件时,文件指针默认指向文件的开头
2、fclose关闭文件
格式:fclose(文件指针);
正常执行则返回0,不成功则返回-1(EOF)
3、练习
以只读、文本方式打开当前路径下一个叫test.txt文件
以只写、二进制方式打开同一个文件
以追加(a)、文本的方式打开同一个文件
同时以读/写、二进制方式打开同一个文件,要求若文件不存在,提示出错
同时以读/些、文本方式打开同一个文件,要求若文件不存在,创建此文件
若打开成功则关闭相应的文件
void test1()
{FILE *fp = NULL; fp = fopen("tset.txt", "r"); // 只读、文本fp = fopen("test.txt","wb"); // 只写、二进制fp = fopen("test.txt","a"); // 追加、文本fp = fopen("tset.txt", "rb+"); // 可读可写、二进制、不存在报错fp = fopen("test.txt","w+"); // 可读可写、文本、不存在创建if(fp != NULL) // 打开成功则关闭相应的文件{fclose(fp); }
}
对文件操作最常用的是:“读”和“写”
C语言提供了多种对文件读写的函数
字节读写函数: fgetc和fputc
字符串读写函数:fgets和fputs
数据块读写函数:fread和fwrite
格式化读写函数:fscanf和fprintf
以上函数可完成对文件内容的顺序读写
(三)文件的字节读写(单个字符的输入输出)
1、fgetc:字节读操作
格式:ch = fgetc(fp);
说明
从指定文件读取一个字节赋给ch(以“读”或“读写的方式”打开文件)
读取文本文件,读到文件结尾返回EOF(EOF是在stdio.h文件中定义的符号常量,值为-1)
读二进制文件,读到文件结尾,使用feof判断结尾(后面会讲)
2、读操作示例
如果本地没有创建相应的文件,会报错如下所示
事先在本地创建a.txt,文件内容为 hello file
文件输出:buf = hello file
void test2()
{char buf[128] = "";int i = 0;FILE* fp = NULL;// 1、使用fopen打开一个文件,获得文件指针fp = fopen("a.txt", "r");if (fp == NULL) // 以只读的形式打开文本,当前目录下没有该文本,输出错误信息,然后退出{perror("fopen");return;}// 2、对文件的操作fgetcwhile (1){// fgetc调用一次 读取到一个字节buf[i] = fgetc(fp);if (buf[i] == EOF) // EOF表示已经到文件末尾{break;}i++;}printf("buf = %s\n", buf);// 3、关闭文件fclose(fp);
}
3、fputc:字节的写操作
格式:fputc(ch,fp);
说明
把一个ch变量中的值(1个字节)写到指定的文件
如果输出成功,则返回输出的字节;如果输出失败,则返回一个EOF
4、写操作示例
void test3()
{char buf[128] = "";int i = 0;FILE* fp = NULL;fp = fopen("b.txt", "w"); // 没有就创建if (fp == NULL){perror("fopen");return;}// 使用fputc进行文件的数据写入printf("请输入要写入文件的字符串:");fgets(buf, sizeof(buf), stdin); // 会获取换行符buf[strlen(buf) - 1] = 0; // 去掉键盘输入的换行符// 将字符串buf中的元素 逐个写入文件中while (buf[i] != '\0'){fputc(buf[i], fp);i++;}fclose(fp);
}
5、练习:从a.txt读取文件内容写入到b.txt
void test4()
{FILE *fp1 =NULL;FILE *fp2 =NULL;// 以只读的方式打开a.txtfp1 = fopen("a.txt","r");if(fp1 == NULL){perror("fopen");return;}// 以只写的方式打开b.txtfp2 = fopen("b.txt","w");if(fp2 == NULL){perror("fopen");return;}// 从fp1中每读取一个字节写入到fp2中while(1){char ch;// 读ch = fgetc(fp1);if(ch == EOF) // 已经读到文件末尾break;// 写fputc(ch,fp2);}fclose(fp1);fclose(fp2);return;
}
(四)字符串的输入输出(文件的字符串读写)
1、fputs:往文件中写入一个字符串
格式:fputs("china", fp);
说明
向指定文件写入一个字符串
第一个参数可以是字符串常量、字符数组、字符指针
字符串末尾的'\0'不会写进文件
void test5()
{// 指针数组char *buf[]={"窗前明月光\n","疑似地上霜\n","举头望明月\n","低头思故乡"};int n = sizeof(buf)/sizeof(buf[0]);FILE *fp = NULL;int i=0;fp = fopen("c.txt", "w");if(fp == NULL){perror("fopen");return;}for(i=0;i<n; i++){fputs(buf[i], fp);}fclose(fp);
}
2、fgets:从文件中获取字符串
格式:fgets(str, n, fp);
说明
功能:从fp指向的文件中读取n-1个字符,在读取n-1个字符之前遇到换行符或EOF,提前结束读取并在最后加一个’\0’
str:存放数据的首地址
返回值:成功读取则返回读到字符串的首元素地址,失败则返回NULL
可以读取换行符
用来获取文件一行的数据
void test6()
{char buf[128] = "";FILE* fp = NULL;char* path = "c.txt"; // path指向文件名为"c.txt"的地址fp = fopen(path, "r");if (fp == NULL){perror("fopen");return;}while (fgets(buf, sizeof(buf), fp)){printf("%s\n", buf);}fclose(fp);
}
3、综合示例
void test7()
{FILE* fp = NULL;char str[10] = "\0";fp = fopen("test1.txt", "w");fputs("XYZ123*#!", fp); // 将字符串"XYZ123*#!"写入文件指针fp指向的当前文件位置fclose(fp);fp = fopen("test1.txt", "r+");fgets(str, 8, fp); // 从文件指针fp指向文件的当前位置读取7个字符存入字符数组str中// 获取字符的长度会比参数给定的长度小1个,因为需要用于存储'\0'puts(str);fclose(fp);
}
4、练习:从一个文件中读取一个字符串,输出到另一个文件
void test8()
{FILE* fp_r, * fp_w; // 文件读写指针char str[100] = "";fp_r = fopen("src.text", "r+");if (fp_r == NULL) // 判断文件是否正常打开{perror(fopen);return;}fp_w = fopen("dest.text", "w+");if (fp_w == NULL){perror(fopen);return;}// 文本输入输出fgets(str, 20, fp_r);puts(str);fputs(str, fp_w);// 键盘输入,屏幕输出fgets(str, 100, stdin);fputs(str, stdout);fclose(fp_r);fclose(fp_w);return 0;
}
(五) 文件块的读写(以二进制的形式读写数据)
1、fwrite:将数据块写入到文件中
格式:fwrite(buffer,size,count,fp);
说明
buffer:指向存储数据空间的首地址的指针
size:一次性读取数据块大小
count:要读取的数据块的个数
fp:指向要进行写操作的文件指针
返回实际读写的数据块数---count(不是总数据大小哦!!!)
void test08()
{// 定义一个结构体,英雄名、喜爱程度、玩的次数HERO hero[] = {{"盾山",100, 150},{"牛魔",80, 20},{"鲁班大师",95, 85},{"东皇",100, 90}};int n = sizeof(hero) / sizeof(hero[0]);FILE* fp = NULL;fp = fopen("hero.txt", "w");if (fp == NULL){perror("fopen");return;}// fwrite将内存的数据原样的输出到文件中// 写入文件的数据不便于用户查看,但是不会影响程序的读fwrite(hero, sizeof(HERO), n, fp);fclose(fp);
}
- 查看的时候发现和自己写入的内容不一样,这就是文件块的特点保存的快,但是查看比较麻烦
2、fread:从文件中读取数据块
格式:fread(buffer,size,count,fp);
参数与fwrite一样
void test10()
{HERO hero[4];int i = 0;FILE* fp = NULL;fp = fopen("hero.txt", "r");if (fp == NULL){perror("fopen");return;}fread(hero, sizeof(HERO), 4, fp); // 结构体数组中有四组数据for (i = 0; i < 4; i++){printf("英雄姓名:《%s》,喜爱程度:《%d》,玩的次数:《%d》\n", \(hero + i) -> name, (hero + i) ->Is_Love, (hero + i) ->Play_NUm);}fclose(fp);
}
3、综合示例
void test11()
{FILE* fp = NULL;int arr[6] = { 1, 2, 3, 4, 5, 6 };fp = fopen("test3.txt", "wb"); // 只写的形式打开二进制文本fwrite(arr, sizeof(int), 6, fp); // 把整型数组arr中6个大小为int类型的数据写入文件指针fp所指向的文件当前位置fclose(fp);int arr2[6] = { 0 };fp = fopen("test3.txt", "rb");fread(arr2, sizeof(int), 6, fp); // 从文件指针fp所指向文件的当前位置读取6个整型大小的数据放入数组arr2中for (int i = 0; i < 6; i++)printf("%d\t", arr2[i]);putchar('\n');fclose(fp);
}
4、练习:从键盘输入一个结构体数组数据,输出到文件,再读入并显示
void test12()
{struct stu boya[10], boyb[2];FILE* fp = NULL;int i = 0;fp = fopen("test12.txt", "wb+");if (fp == NULL){perror(fopen);return;}printf("请输入数据:\n");for (; i < 2; i++){scanf("%s %d %d", boya[i].name, &boya[i].num, &boya[i].age);}fwrite(boya, sizeof(boya), 2, fp); // 学生信息写入文件rewind(fp); // 重新将文件指针指向开头fread(boyb, sizeof(boyb), 2, fp);for (i = 0; i < 2; i++){printf("%s %d %d", boyb[i].name, boyb[i].num, boyb[i].age);}fclose(fp);
}
(六)文件的格式化操作(格式化输入和输出函数)
格式化输入输出:以什么格式输入的就以什么格式输出
针对文件块查看不便的问题,通过格式化输入输出的方法
1、fprintf:格式化写操作
格式:fprintf(文件指针, 格式化字符串, 输出列表);
void test13()
{HERO hero[] = {{"盾山",100, 150},{"牛魔",80, 20},{"鲁班大师",95, 85},{"东皇",100, 90}};int n = sizeof(hero) / sizeof(hero[0]);FILE* fp = NULL;int i = 0;fp = fopen("hero.txt", "w");if (fp == NULL){perror("fopen");return;}for (i = 0; i < n; i++){fprintf(fp, "英雄:%s 喜爱程度:%d 玩的次数:%d\n", hero[i].name, hero[i].Is_Love, hero[i].Play_NUm);}fclose(fp);
}
2、fscanf:格式化读操作
格式:fscanf(文件指针, 格式化字符串, 输入列表);
void test14()
{HERO hero[4];int i = 0;FILE* fp = NULL;fp = fopen("hero.txt", "r");if (fp == NULL){perror("fopen");return;}for (i = 0; i < 4; i++){fscanf(fp, "英雄:%s 喜爱程度:%d 玩的次数:%d\n", hero[i].name, &hero[i].Is_Love, &hero[i].Play_NUm);}for (i = 0; i < 4; i++){printf("%s %d %d\n", hero[i].name, hero[i].Is_Love, hero[i].Play_NUm);}fclose(fp);
}
3、综合示例
优点:对磁盘文件读写使用方便,容易理解,直观的查看
缺点:在输入时将ASCII码转换成二进制,在输出时将二进制转为字符,花费时间较多
struct student { // 学生结构体int id;char name[20];char sex[4];int age;float score;
};
void test15()
{FILE* fp = NULL;struct student S1 = { 1, "小明", "男", 18, 90.5 }, S2;fp = fopen("test15.txt", "w");fprintf(fp, "%d %s %s %d %f\n", S1.id, S1.name, S1.sex, S1.age, S1.score); // 以指定的格式把数据写入文件指针fp所指向的文件中fclose(fp);fp = fopen("test15.txt", "r");fscanf(fp, "%d %s %s %d %f\n", &S2.id, S2.name, S2.sex, &S2.age, &S2.score); // 以指定的格式从文件指针fp所指向的文件中读取一些数据放入结构体变量S2中fclose(fp);
}
(七)格式化输入输出与文件块对比
文件拷贝用文件块read和fwrite函数,速度快,查看不方便
文件打印输出查看用fprintf和fcsanf函数,不在乎时间,需要的是直观可看
在内存与磁盘频繁交换数据的情况下,最好不用fprintf和fcsanf函数,而使用fread和fwrite函数
C语言---14文件操作---01文件内容的顺序读写相关推荐
- 文件操作01 - 零基础入门学习C语言60
第十一章:文件操作01 让编程改变世界 Change the world by program C文件概述 所谓"文件"是指一组相关数据的有序集合.这个数据集有一个名称,叫做文件名 ...
- python对文件的操作都有什么_python中文件操作的相关内容总结(附示例)
本篇文章给大家带来的内容是关于python中文件操作的相关内容总结(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 1. 文件操作介绍 说到操作文件我们肯定会想到流,文件的操 ...
- 【C 语言】文件操作 ( 按照单个字符的方式读写文件 | fgetc 函数 | fputc 函数 )
文章目录 一.文件名路径设置 二.文件打开方式 三.fputc 函数 | 按照字符方式写文件 1.fputc 函数 2.代码示例 四.fgetc 函数 | 按照字符方式读文件 1.fgetc 函数 2 ...
- c语言打开关闭文件的顺序,C语言1-文件概述、文件的打开与关闭、顺序读写数据文件(1).docx...
C语言程序设计教案 章节名称 文件概述.文件的打开与关闭.顺序读写数据文件(1) 授课类型 □理论 □实验 ?理实一体 □实训 □实习 班级 地点 周次 星期 节次 授课进度 ?符合 □超前 □滞后 ...
- C++ 学习笔记之——文件操作和文件流
1. 文件的概念 对于用户来说,常用到的文件有两大类:程序文件和数据文件.而根据文件中数据的组织方式,则可以将文件分为 ASCII 文件和二进制文件. ASCII 文件,又称字符文件或者文本文件,它的 ...
- python关闭读写的所有的文件-Python文件操作:文件的打开关闭读取写入
Python文件操作:文件的打开关闭读取写入 一.文件的打开关闭 Python能以文本和二进制两种方式处理文件,本文主要讨论在Python3中文本文件的操作. 文件操作都分为以下几个步骤: 1.打开文 ...
- .NET基础-11-ArrayList|Hashtable|File文件操作|Dircetioy文件夹操作|Path路径操作
集合 ArrayList与Hashtable应为存在拆箱与装箱,所以性能不怎么好,尽量不要使用,而使用泛型集合 可以使用下面的方式输出所消耗的时间 //ArrayList arl = new Arra ...
- python以写模式打开的文件无法进读操作_Python文件操作:文件的打开关闭读取写入...
Python文件操作:文件的打开关闭读取写入 一.文件的打开关闭 Python能以文本和二进制两种方式处理文件,本文主要讨论在Python3中文本文件的操作. 文件操作都分为以下几个步骤: 1.打开文 ...
- 今天的码农女孩做了关于文件操作和文件拖拽的笔记 2022/1/21
文件操作和文件拖拽 文件操作: js有两种机制:一个是事件机制,一个是io机制 文件操作对象: Blob通过二进制数据读取 file读取单个文件对象 fileList读取多个文件对象 fileRead ...
最新文章
- php 获取key的位置,PHP使用腾讯地图获取指定地址坐标:创建key(图文+视频)
- 麦克风阵列降噪_黄鹂智声降噪耳机E100u,与喧嚣说再见
- x86 vs x64
- linux内核开发_Linux 内核的代码仓库管理与开发流程简介
- linux dump_stack
- Typora 常用技巧
- linux将日期和日历信息追加到文件中_Linux常用指令
- 连通区域的边界点程序
- bzoj1597 土地购买
- int范围内数字的英文读法
- 最小二乘拟合问题求解算法(含python代码)
- Alphabet执行董事长明年1月辞职,谷歌高管大洗牌
- 中国大学MOOC所有课程信息爬虫(课程ID、学校简称、课程名字、教师、学校全称、学生人数、学生人数、评价人数、平均评价)
- 【4500字归纳总结】一名软件测试工程师需要掌握的技能大全
- 百度热力图颜色说明_揭秘!看完徐州城市人口热力图,你就知道该在哪儿买房了...
- 单片机 AD/DA数模转换
- linux红帽子认证费用RHCT,关于RHCE和RHCT认证
- 记:解决 Weditor 页面元素坐标定位不到、不准确的问题
- 王占祥:公募基金券商交易模式
- arr的push,pop,slice.....各种使用方法详细介绍
热门文章
- 流量的秘密—Google Analytics网站分析与优化技巧(第2版)
- 通过浏览器无法访问Hadoop管理页面
- 去水印小程序好做吗?赚钱吗?
- 乘风破浪程序猿,拒绝原地踏步!
- 计算机IP地址pin,打印机的ip地址在机身上哪里,打印机的pin在哪看
- 310569138 294609417 297440781 猪八戒上的骗子
- ElasticSearch:为中文分词器增加对英文的支持(让中文分词器可以处理中英文混合文档)(转)
- CC00388.CloudKubernetes——|KuberNetesCI/CD.V26|——|Jenkins.v06|自动构建Java应用.v06|报错处理|
- 谱聚类(Spectral Clustering)算法介绍
- cpu排行计算机专业,cpu性能天梯图,详细教您电脑cpu排行榜