C语言(C文件处理函数和文件指针)

news2024/12/27 10:56:00

C语言有很多文件操作函数,这里我们挑了一些重要的开始讲,首先说下这些函数都定义在stdio.h头文件中

目录

一.文件指针

二.文件处理函数

1.fopen(打开文件)

2.fclose(关闭文件)

3.getc和putc(从文件指针读取字符)

4.I/O工作原理

5.fprintf和fscanf函数

6.fgets()和fputs()

7.fseek()和ftell

8.fgetpos()和fsetpos()函数

9.ungetc

10.fflush

11.setvbuf()

12.fwrite和fread

13.fepf和ferror

一.文件指针

文件指针的类型是指向FILE的指针,FILE是一个定义在stdin.h的派生类型。文件指针并不是指向实际的文件,它指向一个包含文件信息的数据对象(fopen创建的输入缓冲区)

FILE * fp;

指向标准文件的指针

标准文件

文件指针

通常使用的设备

标准输入

stdin

键盘

标准输出

stdout

显示器

标准错误

stderr

显示器

这些文件指针都是指向FILE的指针,所以它们可用作标准I/O函数的参数,这些文件指针都可以在后面文件处理函数当中使用

二.文件处理函数

1.fopen(打开文件)

FILE* fopen(文件名称,文件模式)

文件名称如果只有一个文件名,则会在可执行文件文件夹位置查找。也可以使用绝对路径和相对路径

该函数用于打开一个文件。第一个参数是待打开文件的名称。第二个参数是一个字符串,指定待打印文件的模式

而模式分为很多种我们来看看

模式字符串

含义

"r"

以读模式打开文件

"w"

以写模式打开文件,把现有文件的长度截为0,如果文件不存在,则创建一个新文件

"a"

以写模式打开文件,在现有文件末尾添加内容,如果文件不存在,则创建一个新文件,存在在现有文件末尾添加内容

"r+"

以读写模式打开文件,

"w+"

以读写模式打开文件,把现有文件的长度截为0,如果文件不存在,则创建一个新文件

"a+"

以读写模式打开文件,在现有文件末尾添加内容,如果文件不存在,则创建一个新文件,存在在现有文件末尾添加内容

"rb","wb","ab","rb+","r+b","wb+","w+b","ab+","a+b"

与上一次模式类似,但是以二进制模式而不是文本模式打开文件

"wx","wbx","w+x","wb+x","w+bx"

(C11)类似非x模式,但是如果文件已存在或以独占模式打开文件,则打开文件失败

这里需要注意下,像UNIX和Linux这样只有一种文件类型的系统,带b字母的模式和不带b字母的模式相同

x是C11新增的,它的功能能让你以fopen()打开一个文件失败时,原文件的内容也不会被删除。还有x模式的独占特性使得其他程序或线程无法访问正在被打开的文件。

fopen()成功打开文件后,会返回一个文件指针

记住打开的时候记得把后缀名加上。此时如果我用w打开,文件内容就没了

fp此时指向的对象值是个垃圾值,因为文件数据都没有了,所以缓冲区内部的值还是原先的垃圾值

关于二进制模式的时候,会在后面讲解二进制文件操作函数的时候讲解的

演示代码:
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>



int main()

{

FILE* fp;

char ch[40];



fp = fopen("test_1.txt", "w");

fgets(ch, 40, fp);



printf("文件内容: %s", ch);

fclose(fp);



return 0;

}

也可以使用绝对路径来操作其他位置的文件

记得\要变为\\,主要为了和转义字符的反斜杠区分开

2.fclose(关闭文件)

关闭指定的文件

fclose(fp)

如果fclose关闭文件成功返回0,否则返回EOF

这里记得结束一定要记得关文件,不然可以会影响其他程序使用文件。而一般磁盘满了或移动磁盘被移除或者I/O错误都会使fclose失败

3.getc和putc(从文件指针读取字符)

getc和putc函数与getchar和putchar函数类似。所不同的是,要告诉getc和putc函数要使用哪一个文件。

格式:

getc: 字符变量 = getc(文件指针)

putc: putc(字符变量,文件指针)

而getc,putc和getchar和putchar区别在于,后者规定要了文件指针

getc(stdin) == getchar()

Putc(ch,sdout) == putchar()

我们来看下实例

演示代码:
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>



int main()

{

FILE* fp;

char ch;



fp = fopen("D:\\C语言练习\\test.txt", "r");

ch = getc(fp);



printf("文件内容: %c", ch);

fclose(fp);



return 0;

}

这里我们来看个有趣的例子

在讲解这个奇怪结果例子之前,我们先来学习一下

4.I/O工作原理

第一步:

fopen()函数打开一个文件,同时还创建了一个缓冲区(在读写模式下创建两个缓冲区)以及一个包含文件和缓冲区数据的结构。另外,fopen()返回一个指向该结构的指针,以便让其他函数知道如何找到该结构。这个结构包含一个指定流中当前位置的文件位置指示器,错误和文件结尾指示器,指向缓冲区开始的指针,文件标识符,计数(统计实际拷贝到缓冲区的字节数)

假设把该结构赋给一个指针变量fp,我们说fopen()函数打开一个流,如果该文本模式打开该文件,就获得一个文本流,如果以二进制模式打开文件,获得二进制流

第二步:

调用文件输入函数,文件中的缓冲大小数据块被拷贝到缓冲区可以使用setvbuf函数来创建缓冲区决定一次读取的字节)。最初调用函数,处理填充缓冲区外,还要设置指针所指向的结构中的值。当前的值从字节0开始。

在初始化结构和缓冲区后,输入函数按要求从缓冲区中读取数据。在它读取数据时,文件位置指示器被设置为指向刚读取字符的下一个字符。又因为stdio.h系列的所有输入函数都使用相同的缓冲区,所以调用任何一个函数都将从上一个函数结束调用的位置开始。

当输入函发现已读完缓冲区中的所有字符时,会请求把下一个缓冲大小的数据块从文件拷贝到该缓冲区中。直到读到结尾最后一个字符,把结尾指示器设为真,于是,下一次调用的输入函数将返回EOF。

输出也一样,也是初始化缓冲区,把值给到缓冲区,当缓冲区满了就会把值送到文件中

在这个基础上我们在来看程序

首先文件test_1原本的内容是helllo world。我们要实现将字符'a'添加到文件末尾,但我们非常意外的发现会出现最终终端打印的内容与我们设想的不一样。这主要因为。在C语言当中。是不允许同时进行读写操作的(现在可以现在容易出问题)。一个输入操作不能随后直接紧跟一个输出操作,同样的一个输出操作也不能直接跟一个输入操作。如果要这样做,必须插入一个fseek函数进行文件光标位置调整。想我们的例子插入后,文件光标已经到了文件结尾,这个时候在继续打印就会出现未定义的错误效果了。

这里我们添加了一个fseek(fp,0L,SEEK_SET)把文件光标定位到了开头,发现效果正确

演示代码:
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>



int main()

{

FILE* fp;

char ch[40];

char c = 'a';



fp = fopen("test_1.txt", "r+");



fgets(ch, 40, fp);

printf("文件内容: %s\n", ch);



putc(c, fp);

fseek(fp, 0L, SEEK_SET);

fgets(ch, 40, fp);

printf("文件内容: %s\n", ch);



fclose(fp);



return 0;

}

5.fprintf和fscanf函数

文件I/O函数fprint()和fscanf()函数的工作方式和printf()和scanf()类似,区别在于前者需要用第一个参数指定待处理的文件

格式:

fprintf(文件指针,"字符串",占位符数值),pritnf是将内容直接输入到屏幕上,而fprintf将内容输入到指定文件中。

fprintf(stdout,"hello") == printf("hello")

fscanf(文件指针,"占位符",变量),scanf是通过键盘输入值,而fscanf通过文件输入值到变量中。

fscanf(stdint,"%d",&num) == scanf("%d",&num);

                                                                                                                                                                                                                                                                                                                

6.fgets()和fputs()

fgets(),用于将文件写入文件,第一个参数表示存储输入位置的地址,第二个参数是一个整数,第三个参数是一个文件指针,指定待读取的文件

fgets(buf,STLEN,fp)

buf是char类型数组的名称,STLEN是字符串的大小,fp是指向FILE的指针

fgets()函数读取输入知道第一个换行符的后面,或读到文件结尾,或者读取STLEN-1个字符。然后,fgets()在末尾添加一个空字符使之成为一个字符串。字符串的大小是其字符串加上一个空字符。如果fgets()在读到字符上限之前已读完一整行,它会把表示行结尾的换行符放在空字符前面。fgets()函数在遇到EOF时返回NULL值如果为遇到EOF则放回之前传给它的第一个参数地址。

fputs()函数接受两个参数,第一个是字符串的地址,第二个是文件指针。Fputs()在打印字符串时不会在其末尾添加换行符

fputs(buf,fp);

buf是字符串的地址,fp用于指定目标文件

7.fseek()和ftell

有了fseek()函数,便可把文件看作时数组,在fopen()打开的文件中直接移动到任意字节处。

Fseek()第一个参数是FILE指针,指向待查找的文件。第二个参数是偏移量,该函数表示从起始点开始要移动的距离。该参数必须是一个long类型的值,可以为正,负或0。第三个参数是模式,该参数确定起始点。下面我们俩看几个文件的起始点模式

模式

偏移量的起始点

SEEK_SET

文件开始处

SEEK_CUR

当前位置

SEEK_END

文件末尾

Fseek(fp,0L,SEEK_SET);  //定位至文件开始处

Fseek(fp,10L,SEEK_SET);  //定位至文件中的第10个字节

Fseek(fp,2L,SEEK_CUR);  //从文件当前位置前移2个字节

Fseek(fp,0L,SEEK_END);  //定位到文件结尾

Fseek(fp,-10L,SEEK_END);  //从文件结尾处回退10个字节

如果一切正常,fseek()的返回值为0,如果错误,则返回-1

ftell()函数的返回类型是Long,它返回的参数指向文件的当前位置据文件开始处的字节数。(文件的第一个字节到文件开始处的距离是0),对于MS-DOS,ftell()返回的值把\r\n当作一个字节激素

这个例子当中我们通过ftell获得了putc后文件光标的位置12,然后使用fseek函数移动光标后,在用ftell光标位置如我们设置的那样变到了位置0

演示代码:

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>



int main()

{

FILE* fp;

char ch[40];

char c = 'a';



fp = fopen("test_1.txt", "r+");



fgets(ch, 40, fp);

printf("文件内容: %s\n", ch);



putc(c, fp);

printf("文件当前光标位置: %ld\n",ftell(fp));

fseek(fp, 0L, SEEK_SET);

printf("文件当前光标位置: %ld\n",ftell(fp));

fgets(ch, 40, fp);

printf("文件内容: %s\n", ch);



fclose(fp);



return 0;

}

8.fgetpos()和fsetpos()函数

这两个参数在fseek和ftell的基础上增加了处理较大文件的功能。它们不使用long类型的值,用一种新类型fpos_t,fpos_t类型的变量和数据对象可以在文件中指定一个位置

Int fgetpos(FILE * restrict stream,fpos_t * restrict pos)

调用该函数时,它把fpos_t类型的值放在pos指定的位置上,该值描述了文件中的当前位置距文件开头的字节数。如果成功返回0,失败,返回非0

Int fsetpos(FILE * stream,const fpos_t *pos);

调用该函数时,使用pos指向位置上的fpos_t类型值来设置文件指针指向偏移该值后指定的位置。成功,返回0,失败,返回非0

9.ungetc

Int ungetc(int c,FILE *fp)

该函数把c指定的字符放回输入流中

10.fflush

Int fflush(FILE * fp);

该函数引起输出缓冲区中所有的未写入数据发送到fp指定的输出文件。这个过程我们也称为刷新缓冲区

11.setvbuf()

Int setvbuf(FILE * restrict fp,char * restrict buf,int mode,size_t size)

该函数创建一个供标准I/O函数替换使用的缓冲区

fp:指定待处理的流

buf:指定待使用的存储区,如果不是NULL,则必须创建一个缓冲区(为NULL,函数会为自动分配一个缓冲区)

mode:模式选择 _IOFBF 完成缓冲(在缓冲区满时刷新)  ——IOLBF行缓冲(在缓冲区满时或写入一个换行符时)

_IONBF 无缓冲

size:大小

如果操作成功返回0,失败非零0

12.fwrite和fread

为了确保数值在存储前后一致,最精确的做法时使用与计算机相同的为组合来存储。如果以程序所用的表示法数据存储在文件中,则称以二进制形式存储数据。

实际上,所有的数据都是以二进制形式存储的,甚至连字符都以字符码的二进制表示来存储。如果文件中的所有数据都被解释成字符码,则称该文件包含文本数据。如果部分或所有的数据都被解释成二进制形式的数值数据,则称该文件包含二进制数据。

fwrite()原型

size_t fwrite(const void * restrict ptr,size_t size,size_t nmemb,FILE * restrict fp);

ptr:待写入数据块的地址

size:待写入数据块的大小(以字节为大小)

nmemb:待写入的数据块数量

fp:待写入的文件

fwrite(earnings,sizeof(double),10,fp);

把earnings数组中的数据写入文件,数据被分为10块,每块都是double的大小

fwrite()函数返回成功写入项的数量。

fread()原型

Size_t fread(void * restrict ptr,size_t size,size_t nmemb,FILE * restrict fp);

ptr:待读取文件数据在内存中的地址

fp:指定待读取的文件

fread(earnings,sizeof(double),10,fp);

调用10个double大小的值拷贝进earnings数组中

fread()函数返回成功读取项的数量

这里要知道,ANSI C把指向void得指针作为一种通用指针,用于指针指向不同类型得情况,void * restrict可以是指向一个double类型得数组指针,也可能是指向其他类型结构得指针

在这个例子中,我们将ch数组的字符串通过fwrite以12个字节为一次进行传递(传递一次就够了)到test_1.txt文本中。然后又通过fread读取了fp开始的12个字节到ch_t数组中,进行打印。结果最终正确。

演示代码:

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>



int main()

{

FILE* fp;

char ch[] = "hello world";

char ch_t[12];

fp = fopen("test_1.txt", "rb+");

fwrite(ch, strlen(ch) + 1, 1, fp);

rewind(fp);

fread(ch_t, 12, 1, fp);

printf("ch_t: %s", ch_t);

return 0;

}

13.fepf和ferror

Int feof(FILE * fp)

Int ferror(FILE *fp)

如果标准输入函数返回EOF,则通常表面函数已到达文件结尾。然而,出现读取错误时,函数也会返回EOF。

当上一次输入调用检测到文件结尾时,feof()函数会返回一个非零值,否则返回0

而当读或写出现错误,ferror()函数返回一个非零值,否则返回0


好了朋友们我们今天的内容到这就结束了,今天的内容到这里就结束了,如果有啥不会的朋友记得论坛里面提问哈~

如果朋友你感觉文章的内容对你有帮助,可以点赞关注文章和专栏以及关注我哈,嘿嘿嘿我会定期更新文章的,谢谢朋友你的支持哈

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/339738.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

「C++控制台生存游戏」暗黑体素 DarkVoxel 控制台版

“《只有作者能看懂的一款游戏》” 刚进高中前开始写的一款抽象的生存游戏 BUG很多请见谅 ###【点击此处&#xff0c;免费畅玩】### 类似泰拉瑞亚的一款游戏 『暗黑体素 DarkVoxel』 直接上图&#xff01; 用控制台写出如此奇葩的生存游戏&#xff0c;可谓世间少有。 操作…

2022黑马Redis跟学笔记.实战篇(二)

2022黑马Redis跟学笔记.实战篇 二实战篇Redis开篇导读4.1短信登录4.1.1. 搭建黑马点评项目一、导入黑马点评项目二、导入SQL三、有关当前模型四、导入后端项目相关依赖配置redis和mysql连接项目组成概述关闭Linux防火墙五、导入前端工程六、 运行前端项目4.1.2. 基于Session实现…

选购交换机的参数依据和主要的参数指标详解

如何选购交换机&#xff1f;用什么交换机&#xff1f;在选购交换机时交换机的优劣无疑十分的重要&#xff0c;而交换机的优劣要从总体构架、性能和功能三方面入手。交换机选购时。性能方面除了要满足RFC2544建议的基本标准&#xff0c;即吞吐量、时延、丢包率外&#xff0c;随着…

网络是怎么连接笔记(一)WEB浏览器

文章目录介绍生成HTTP请求消息向DNS服务器查询WEB服务的IP地址全世界DNS服务器的大接力委托协议栈发送消息介绍 互联网整个消息传递流程 生成HTTP请求消息向DNS服务器查询WEB服务的IP地址然后DNS服务器进行查询IP地址委托协议给对应IP发送消息 生成HTTP请求消息 整个网络发…

Spring面试重点(三)——AOP循环依赖

Spring面试重点 AOP 前置通知&#xff08;Before&#xff09;&#xff1a;在⽬标⽅法运行之前运行&#xff1b;后置通知&#xff08;After&#xff09;&#xff1a;在⽬标⽅法运行结束之后运行&#xff1b;返回通知&#xff08;AfterReturning&#xff09;&#xff1a;在⽬标…

2023年前端面试知识点总结(CSS篇)

近期整理了一下高频的前端面试题&#xff0c;分享给大家一起来学习。如有问题&#xff0c;欢迎指正&#xff01; 1. 对CSS盒模型的理解 CSS3的盒模型有两种盒子模型&#xff1a;标准盒子模型、IE盒子模型 盒模型都是由四个部分组成的&#xff0c;分别是content&#xff08;内容…

layui框架学习(6:基础菜单)

菜单是应用系统的必备元素&#xff0c;虽然网页中的导航也能作为菜单使用&#xff0c;但菜单和导航的样式和用途有所不同&#xff08;不同之处详见参考文献5&#xff09;。Layui中用不同的预设类定义菜单和导航的样式&#xff0c;同时二者依赖的模块也不一样。本文主要学习和记…

Vue (3)

文章目录1. 数据代理1.1 回顾1.2 开始2. 事件处理2.1 v-on:click 点击事件2.2 事件修饰符2.3 键盘事件3. 计算属性3.1 插值语法实现3.2 methods实现3.3 计算属性实现4. 监视属性4.1 深度监视4.2 监视属性的简写形式4.3 watch 与 computed 对比1. 数据代理 在学习 数据代理 时 先…

SQL数据查询——单表查询和排序

文章目录一、单表查询1.查询列1&#xff09;查询全部列指定列2&#xff09;查询经过计算的值3&#xff09;列的别名2.查询元组1&#xff09;消除取值重复的行(DISTINCT)2&#xff09;条件查询(WHERE)3.空值参与运算4.着重号二、排序(ORDER BY子句)一、单表查询 单表查询指仅涉及…

Webpack的知识要点

在前端开发中&#xff0c;一般情况下都使用 npm 和 webpack。   npm是一个非常流行的包管理工具&#xff0c;帮助开发者管理项目中使用的依赖库和工具。它可以方便地为项目安装第三方库&#xff0c;并在项目开发过程中进行版本控制。   webpack是一个模块打包工具&#xff…

C语言深度剖析之程序环境和预处理

1.程序的翻译环境和执行环境 第一种是翻译环境&#xff0c;在这个环境中源代码被转换为可执行的机器指令 第二种是执行环境&#xff0c;它用于实际执行代码 2.翻译环境 分为四个阶段 预编译阶段 &#xff0c;编译&#xff0c;汇编&#xff0c;链接 程序编译过程&#xff1a;多个…

使用vue3,vite,less,flask,python从零开始学习硅谷外卖(16-40集)

严正声明&#xff01; 重要的事情说一遍&#xff0c;本文章仅供分享&#xff0c;文章和代码都是开源的&#xff0c;严禁以此牟利&#xff0c;严禁侵犯尚硅谷原作视频的任何权益&#xff0c;我知道学习编程的人各种各样的心思都有&#xff0c;但这不是你对开源社区侵权的理由&am…

iptables防火墙之SNAT与DNAT

目录 1、SNAT策略概述 1.SNAT策略的典型应用环境 2.SNAT策略的原理 3.SNAT工作原理 4.SNAT转换前提条件 5.开启SNAT命令 6.SNAT转换 2.SNAT示例 1. 配置网关服务器 2.Xshell 连接192.168.100.100 3.DNAT策略及应用 1. DNAT策略概述 2.DNAT 策略的应用 3.DNAT转换前提条件…

看完这篇 教你玩转渗透测试靶机vulnhub——Hack Me Please: 1

Vulnhub靶机Hack Me Please: 1渗透测试详解Vulnhub靶机介绍&#xff1a;Vulnhub靶机下载&#xff1a;Vulnhub靶机安装&#xff1a;Vulnhub靶机漏洞详解&#xff1a;①&#xff1a;信息收集&#xff1a;②&#xff1a;漏洞利用③&#xff1a;获取反弹shell&#xff1a;④&#x…

how https works?https工作原理

简单一句话&#xff1a; https http TLShttps 工作原理&#xff1a;HTTPS (Hypertext Transfer Protocol Secure)是一种带有安全性的通信协议&#xff0c;用于在互联网上传输信息。它通过使用加密来保护数据的隐私和完整性。下面是 HTTPS 的工作原理&#xff1a;初始化安全会…

Camtasia2023最新版电脑视频录屏记录编辑软件

在Mac或Wind上有各种可用的视频记录和编辑软件&#xff0c;其中Camtasia被称为视频记录器和视频编辑器。录屏软件Camtasia2023到底有什么特色功能&#xff1f;本文将帮助您选择理想的选择来开始视频捕获&#xff0c;创建和编辑。Camtasia2023是Mac/win平台上一款使用非常简单的…

【JavaScript】题(牛客网)——熟练使用函数调用,超详细讲解

1 熟练使用函数调用 1.1 题目 执行以下程序&#xff0c;输出结果为 var uname "window"; var object {uname: "object",fun: function () {console.log(this.uname);return function () {console.log(this.uname);};}, };object.fun()();1.2 答案 ob…

ThingsBoard-设备配置

1、概述 从 ThingsBoard 3.2 开始,租户管理员可以使用设备配置文件为多个设备配置通用设置。每个设备在单个时间点都有一个且唯一的配置文件。 有经验的 ThingsBoard 用户会注意到设备类型已被弃用,取而代之的是设备配置文件。更新脚本将根据唯一的设备类型自动创建设备配置…

三、Java面向对象

1 . 方法 方法(method)是程序中最小的执行单元方法就是一些代码的打包 需要的时候可以直接调用方法之间是平级的关系 不能在方法里面定义方法方法不调用就不执行 方法的定义 // 方法的定义 /* [修饰符] 返回值类型 方法名称([参数 1],[参数 2]){语句A;return 返回值; } *///…

VT虚拟化框架编写

文章目录前言VT架构基础VT框架编写步骤一&#xff1a;检测VT是否开启VMM和VMVMON和VMCSVT框架编写步骤二 填充VMONVT框架编写步骤三 进入VTVT框架编写步骤四 初始化VMCSVT框架编写步骤五 初始化VMCS数据区VT框架编写步骤六 处理必要事件前言 学习VT相关的知识&#xff0c;需要…