【C语言】文件操作详解
文章目录
- 前言
- 一、文件是什么
- 二、文件具体介绍
- 1.文件名
- 2.文件类型
- 3.文件缓冲区
- 4.文件指针
- 5.文件的打开和关闭
- 三、文件的顺序读写
- 1.字符输入函数(fgetc)
- 2.字符输出函数(fputc)
- 3.文本行输入函数(fgets)
- 4.文本行输出函数(fputs)
- 5.二进制输入(fread)
- 6.二进制输出(fwrite)
- 四、文件随机读写
- 1.fseek
- 2.ftell
- 3.rewind
- 总结
添加链接描述
前言
大家好呀,今天小小樊为大家分享一下自己对于C语言中文件操作学习的理解,希望可以帮助到大家!!!
`
一、文件是什么
磁盘上的文件是文件。
但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件
程序文件
包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)。
数据文件
文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。
本篇讨论的是数据文件。
二、文件具体介绍
1.文件名
一个文件要有一个唯一的文件标识,以便用户识别和引用。
文件名包含3部分:文件路径+文件名主干+文件后缀
例如: c:\code\test.txt
为了方便起见,文件标识常被称为文件名。
2.文件类型
根据数据的组织形式,数据文件被称为文本文件或者二进制文件。
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件。
一个数据在内存中是怎么存储的呢?
字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储。
如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节
#include <stdio.h>
int main()
{
int a = 10000;
FILE* pf = fopen("test.txt", "wb");
fwrite(&a, 4, 1, pf);//二进制的形式写到文件中
fclose(pf);
pf = NULL;
return 0;
}
3.文件缓冲区
系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐
个地将数据送到程序数据区(程序变量等)。
我们可以对缓冲区的存在进行验证:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<windows.h>int main()
{char arr[20] = "zhangjiawang";FILE* pf = fopen("test.txt", "w");if (pf == NULL){perror("fopen:");return 1;}fputs(arr,pf);//数据放在了输出缓冲区上Sleep(10000);//睡眠10秒fflush(pf);//刷新缓冲区,才能将输出缓冲区的数据写到文件上Sleep(10000);//睡眠10秒在看fclose(pf);//关闭文件,也会刷新缓冲区pf = NULL;return 0;
}
这个时候还未写入文件
这个时候就写入文件了!!
4.文件指针
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及
文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名FILE.
一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。
下面我们可以创建一个FILE*的指针变量:
定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文
件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件。
5.文件的打开和关闭
FILE * fopen ( const char * filename, const char * mode );//打开文件的函数,第一个参数文件名,第二个参数打开方式int fclose ( FILE * stream );//关闭文件的函数,参数接收文件信息区的起始地址
打开方式:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{FILE* fp = fopen("1.txt", "r");//打开该文件的话,就会将该文件的文件信息区的首地址传给文件指针FILE*fp,打不开返回空地址,表明错误if (fp == NULL){perror("fopen:");//打印错误return 1;//异常退出}fclose(fp);//关闭文件fp = NULL;//文件指针置为空指针,防止出现野指针
}
当打开文件时,该文件并没有创建,用读“r’‘的方式去打开文件时,不会存在对应文件的文件信息区,则不会返回对应文件信息区的地址,返回一个空指针,打印错误原因
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{FILE* fp = fopen("1.txt", "w");if (fp == NULL){perror("fopen:");return 1;}fclose(fp);fp = NULL;
}
当以"w"方式打开文件,如果没有该文件会重新创建一个该文件
三、文件的顺序读写
1.字符输入函数(fgetc)
函数声明:int fgetc( FILE *stream );
参数:要读取的文件的文件指针变量
返回值:读取成功返回读取到的字符,读取到文件末尾或读取失败则返回EOF,EOF是个负数,这也是为什么用返回值类型为int,而不是char
从文件中读到字符变量中
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
int main()
{FILE* fp = fopen("2.txt", "r");if (fp == NULL){perror("fopen");return 1;}char ch=fgetc(fp);printf("%c", ch);fclose(fp);fp = NULL;
}
一次只能读一个字符
要想使用fgetc全读出paopao
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
int main()
{FILE* fp = fopen("2.txt", "r");if (fp == NULL){perror("fopen");return 1;}char ch;while ((ch = fgetc(fp)) != EOF)//没到文件结尾,循环读字符{printf("%c", ch);}fclose(fp);fp = NULL;
}
注意:你要读文件必须先存在文件,并且有内容才能读到,打开文件方式“r"
2.字符输出函数(fputc)
函数声明:int fputc(int char, FILE *stream)
参数:char 要被写入的字符。该字符以其对应的 int 值进行传递。 stream – 这是指向 FILE 对象的指针,接收文件信息区的地址,该 FILE对象(对应的文件信息区)标识了要被写入字符的流。
返回值:如果没有发生错误,则返回被写入的字符。如果发生错误,则返回 EOF,并设置错误标识符。
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
int main()
{FILE* fp = fopen("2.txt", "w");if (fp == NULL){perror("fopen");return 1;}fputc('a', fp);fputc('a', fp);fputc('a', fp);fclose(fp);fp = NULL;
}
注意:同一个文件再次写入时,用“w"打开文件,文件之前内容被覆盖
3.文本行输入函数(fgets)
函数声明:char *fgets(char *s, int size, FILE *stream);
参数:s接收的时从文件中读到字符串数组的地址,size是从文件中一次读几个字符,stream接收对应文件信息区地址
返回值:成功返回字符串,错误或文件结束条件返回NULL。
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
int main()
{FILE* fp = fopen("2.txt", "r");if (fp == NULL){perror("fopen");return 1;}char arr[256];//定义字符数组fgets(arr,10,fp);//从文件读取字符到数组printf("%s", arr);//打印字符数组fclose(fp);fp = NULL;
}
注意:最后会读一个‘\0’给字符数组
4.文本行输出函数(fputs)
函数声明:int fputs(const char *s, FILE *stream);
参数: s 代表要输出的字符串的首地址,stream接收文件信息区的地址
返回值:该函数返回一个非负值,如果发生错误则返回 EOF。
int main()
{FILE* fp = fopen("2.txt", "w");if (fp == NULL){perror("fopen");return 1;}char arr[256]="abc";fputs(arr,fp);//printf("%s", arr);fclose(fp);fp = NULL;
}
也可以直接传字符串,也相当于接收字符串起始地址
5.二进制输入(fread)
函数声明:size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
参数:参数1:文件读到内存的位置.参数2:读到基本单元字节大小.参数3:读到基本单元字节个数4:文件指针 ;
返回值:返回读取或回写的记录数,数据项的个数,fread是一个函数。从一个文件流中读数据,最多读取count个元素,每个元素size字节,如果调用成功返回实际读取到的元素个数,如果不成功或读到文件末尾返回 0。
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
int main()
{FILE* fp = fopen("2.txt", "rb");if (fp == NULL){perror("fopen");return 1;}char arr[256] = {0};int sz=sizeof(arr);while (!feof(fp))//使用 feof(fp) 判定文件是否读取完毕 , 如果返回 1 说明文件没有读取完毕 , 返回 0 , 说明文件读取完毕{fread(arr, 1, sz-1, fp);//为了避免乱码出现,参数3传入字符串长度大小-1,不会出现乱码}printf("%s", arr);fclose(fp);fp = NULL;
}
6.二进制输出(fwrite)
函数声明:size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
参数:参数1:文件从内存读取数据的位置.参数2:读到基本单元字节大小.参数3:读到基本单元字节个数4:文件指针 ;
返回值: size_t 返回值返回的是实际写出到文件的 基本单元 个数 。
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
int main()
{FILE* fp = fopen("2.txt", "wb");if (fp == NULL){perror("fopen");return 1;}char arr[] = "yuebanxiaoyequ";int sz=sizeof(arr);fwrite(arr,1, sz-1, fp);fclose(fp);fp = NULL;
}
四、文件随机读写
1.fseek
根据文件指针的位置和偏移量来定位文件指针。
函数声明:int fseek ( FILE * stream, long int offset, int origin );
参数:stream文件指针。offset偏移量参数,为正向文件结尾偏移,为负向文件开头偏移,origin为开始偏移的位置,有3种取值
文件头 SEEK_SET
当前位置 SEEK_CUR
文件尾 SEEK_END
2.ftell
返回文件指针相对于起始位置的偏移量
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
int main()
{FILE* fp = fopen("2.txt", "rb");if (fp == NULL){perror("fopen");return 1;}char arr[256] = { 0 };int sz = sizeof(arr);fseek(fp,6,SEEK_SET);int num = ftell(fp);//num的返回值应该是偏移量6printf("%d ", num);while (!feof(fp))//使用 feof(fp) 判定文件是否读取完毕 , 如果返回 1 说明文件没有读取完毕 , 返回 0 , 说明文件读取完毕{fread(arr, 1, sz - 1, fp);//为了避免乱码出现,参数3传入字符串长度大小-1,不会出现乱码}printf("%s", arr);fclose(fp);fp = NULL;
}
3.rewind
让文件指针的位置回到文件的起始位置
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
int main()
{FILE* fp = fopen("2.txt", "rb");if (fp == NULL){perror("fopen");return 1;}char arr[256] = { 0 };int sz = sizeof(arr);fseek(fp,6,SEEK_SET);rewind(fp);//回到原点int num = ftell(fp);//num此时为0,并且打印文件中所有信息printf("%d ", num);while (!feof(fp))//使用 feof(fp) 判定文件是否读取完毕 , 如果返回 1 说明文件没有读取完毕 , 返回 0 , 说明文件读取完毕{fread(arr, 1, sz - 1, fp);//为了避免乱码出现,参数3传入字符串长度大小-1,不会出现乱码}printf("%s", arr);fclose(fp);fp = NULL;
}
总结
文件操作中常用的知识就是这些啦,这些就是博主的全部理解啦,希望能够帮助到各位读者,如有不正确的地方,还请大家指正,谢谢大家!!!
相关文章:

【C语言】文件操作详解
文章目录 前言一、文件是什么二、文件具体介绍1.文件名2.文件类型3.文件缓冲区4.文件指针5.文件的打开和关闭 三、文件的顺序读写1.字符输入函数(fgetc)2.字符输出函数(fputc)3.文本行输入函数(fgets)4.文本…...

栈(Stack)的详解
目录 1.栈的概念 2.栈的模拟实现 1.栈的方法 2.模拟栈用(整型)数组的形式呈现 2.1栈的创建 2.2压栈 2.3栈是否为空 2.4出栈 2.5获取栈中有效元素个数 2.6获取栈顶元素 2.7完整代码实现 1.栈的概念 从上图中可以看到, Stack 继承了…...

深入了解GCC编译过程
关于Linux的编译过程,其实只需要使用gcc这个功能,gcc并非一个编译器,是一个驱动程序。其编译过程也很熟悉:预处理–编译–汇编–链接。在接触底层开发甚至操作系统开发时,我们都需要了解这么一个知识点,如何…...

leetcode 594.最长和谐子序列(滑动窗口)
⭐️ 题目描述 🌟 leetcode链接:最长和谐子序列 思路: 第一步先将数组排序,在使用滑动窗口(同向双指针),定义 left right 下标,比如这一组数 {1,3,2,2,5,2,3,7} 排序后 {1,2,2,2,3,…...

深入剖析云计算与云服务器ECS:从基础到实践
云计算已经在不断改变着我们的计算方式和业务模式,而云服务器ECS(Elastic Compute Service)作为云计算的核心组件之一,为我们提供了灵活、可扩展的计算资源。在本篇长文中,我们将从基础开始,深入探讨云计算…...

苍穹外卖技术栈
重难点详解 1、定义全局异常 2、ThreadLocal ThreadLocal 并不是一个Thread,而是Thread的一个局部变量ThreadLocal 为每一个线程提供独立的存储空间,具有线程隔离的效果,只有在线程内才能取到值,线程外则不能访问 public void …...

重新开始 杂类:C++基础
目录 1.输入输出 2 . i 与 i 3.结构体 4.二进制 1.输入输出 #include<cstdio>//cin>>,cout #include<iostream>//printf,scanf (1) cin , cout输入输出流可直接用于数字,字符 (2)scanf(&quo…...

自用的markdown与latex特殊符号
\triangleq \approx \xlongequal[y\arctan x]{x\tan y} \sum_{\substack{j1 \\ j\neq i}} \iiint\limits_\Omega \overset{\circ}{\vec{r}} \varphi \checkmark \stackrel{\cdot\cdot\cdot}{x}≜ ≈ y arctan x x tan y ∑ j 1 j ≠ i ∭ Ω r ⃗ ∘ φ ✓ x ⋅ ⋅ ⋅…...

【20期】说一说Java引用类型原理
Java中一共有4种引用类型(其实还有一些其他的引用类型比如FinalReference):强引用、软引用、弱引用、虚引用。 其中强引用就是我们经常使用的Object a new Object(); 这样的形式,在Java中并没有对应的Reference类。 本篇文章主要是分析软引用、弱引用、…...

无锡布里渊——厘米级分布式光纤-锅炉安全监测解决方案
无锡布里渊——厘米级分布式光纤-锅炉安全监测解决方案 厘米级分布式光纤-锅炉安全监测解决方案 1、方案背景与产品简介: 1.1:背景简介: 锅炉作为一种把煤、石油或天燃气等化石燃料所储藏的化学能转换成水或水蒸气的热能的重要设备ÿ…...

GREASELM: GRAPH REASONING ENHANCED LANGUAGE MODELS FOR QUESTION ANSWERING
本文是LLM系列文章,针对《GREASELM: GRAPH REASONING ENHANCED LANGUAGE MODELS FOR QUESTION ANSWERING》的翻译。 GREASELM:图推理增强的问答语言模型 摘要1 引言2 相关工作3 提出的方法:GREASELM4 实验设置5 实验结果6 结论 摘要 回答关…...

QT C++ 实现网络聊天室
一、基本原理及流程 1)知识回顾(C语言中的TCP流程) 2)QT中的服务器端/客户端的操作流程 二、代码实现 1)服务器 .ui .pro 在pro文件中添加network库 .h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>…...

每日一道面试题之什么是上下文切换?
上下文切换是指在计算机操作系统中,当多个进程或线程同时运行时,系统需要将当前运行进程或线程的状态(包括程序计数器、寄存器值、内存映像等)保存起来,然后切换到另一个进程或线程继续执行的过程。上下文切换通常由操…...

2023.9.3 关于 AVL 树
目录 二叉搜索树 二叉搜索树的简介: 二叉搜索树的查找: 二叉搜索树的效率: AVL树 AVL 树的简介: AVL 树的实现: AVL树的旋转 右单旋 左单旋 左右双旋 右左双旋 完整 AVL树插入代码 验证 AVL 树 AVL 树的性…...

机器学习课后习题 --- 机器学习实践
(一)单选题 1.以下关于训练集、验证集和测试集说法不正确的是( )。 A:测试集是纯粹是用于测试模型泛化能力B:训练集是用来训练以及评估模型性能 C:验证集用于调整模型参数 D:以上说法都不对 2.当数据分布不平衡时,我们可采取的措施不包括…...

git常用操作
删除分支 例:例如想删除的分支是dev_delete,那么可以按照如下的操作进行 #查看当前所在分支 git branch#如果在当前dev_delete分支上,就要切换到其他分支才能删除该分支 git checkout 其他分支#删除本地名为dev_delete的分支 git branch -d dev_delete…...

QT的补充知识
一、文件 QFile QT提供了QFile类用于对文件进行读写操作,也提供了其他的两个类:文本流(QTextSream)和数据流(QDataStream) 文本流(QTextSream):用于对文本数据的处理&am…...

【力扣周赛】第 360 场周赛(贪心 ⭐树上倍增)
文章目录 竞赛链接Q1:8015. 距离原点最远的点(贪心)Q2:8022. 找出美丽数组的最小和(贪心)Q3:2835. 使子序列的和等于目标的最少操作次数(贪心)思路竞赛时丑陋代码&#x…...

企业如何防止数据外泄——【部署智能透明加密防泄密系统】
为防止公司文件泄密,可以采取以下措施: www.drhchina.com 分部门部署:根据不同的部门需要,为不同部门用户部署灵活的加密方案。例如,对研发部、销售部、运营部的机密资料进行强制性自动加密,对普通部门的文…...

【聚类】DBCAN聚类
OPTICS是基于DBSCAN改进的一种密度聚类算法,对参数不敏感。当需要用到基于密度的聚类算法时,可以作为DBSCAN的一种替代的优化方案,以实现更优的效果。 原理 基于密度的聚类算法(1)——DBSCAN详解_dbscan聚类_root-ca…...

通过安装cpolar内网穿透在Kali上实现SSH远程连接的步骤指南
文章目录 1. 启动kali ssh 服务2. kali 安装cpolar 内网穿透3. 配置kali ssh公网地址4. 远程连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 简单几步通过cpolar 内网穿透软件实现ssh 远程连接kali! 1. 启动kali ssh 服务 默认新安装的kali系统会关闭ssh 连接服务,我们通…...

UDP和TCP协议报文格式详解
在初识网络原理(初识网络原理_蜡笔小心眼子!的博客-CSDN博客)这篇博客中,我们简单的了解了一下TCP/IP五层网络模型,这篇博客将详细的学习一下五层网络模型中传输层的两个著名协议:UDP和TCP 目录 一, 传输层的作用 二, UDP 1,UDP协议的特点 2,UDP报文格式 三, TC…...

STM32+UART串口+DMA收发
目录 1、cubemax端配置 1.1 初始化配置 1.2 GPIO配置 1.3 UART配置 1.3.1 串口基础配置 1.3.2 DMA配置 2、keil端代码设计 2.1 初始化配置 2.2 DMA接收初始化配置 2.3 DMA发送配置 2.4 接收回调函数设置 2.5 回调函数内容代码编写 2.5.1 接收回调函数 2.5.2 发送回调…...

安全基础 --- js的闭包和this属性
js闭包 简介 一个函数和对其周围状态(lexical exviroment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure) 在js中,通俗来讲,…...

【C语言每日一题】08. 字符三角形
题目来源:http://noi.openjudge.cn/ch0101/08 08 字符三角形 总时间限制: 1000ms 内存限制: 65536kB 问题描述 给定一个字符,用它构造一个底边长5个字符,高3个字符的等腰字符三角形。 输入 输入只有一行, 包含一个字符。 输出…...

如何打war包,并用war包更新服务器版本
1.打包,我用的maven打包 先执行clean将已经生成的包清除掉 清除完,点package进行打包 控制台输出success,证明打包成功了 文件名.war的后缀就是生成的war包 2.将war包上传致服务器 一般会在war包加上日期版本上传至服务器 解压上传的war…...

uniApp webview 中调用底座蓝牙打印功能异常
背景: 使用uniApp, 安卓底座 webView 方式开发; 调用方式采用H5 向 底座发送消息, 底座判断消息类型, 然后连接打印机进行打印; 内容通过指令集方式传递给打印机; 过程当中发现部分标签可以正常打印, 但又有部分不行,打印机没反应, 也没有报错; 原因分析: 对比标签内容…...

Mac下安装Jmeter及其配置
一、安装JDK环境 安装方式:mac下配置JDK环境_只看不学的博客-CSDN博客 如果已安装JDK环境即可忽略该步骤,检查方式,在终端输入java -version,如果出现了java版本,即代表已经配置过JDK环境了,如下图所示: …...

js+html实现打字游戏v1
实现逻辑:设置定时器每秒刷新一次,定时器刷新多少次执行一次生成单词操作来决定单词的生成速度,例如初始单词生成速度为1,那么定时器刷新5次才生成一次单词,每个单词用span来装,每组10个单词放到div里。监听…...

Java on VS Code 8月更新|反编译器用户体验优化、新 Maven 项目工作流、代码高亮稳定性提升
作者:Nick Zhu 排版:Alan Wang 大家好,欢迎来到 Visual Studio Code for Java 的 8 月更新!在这篇博客中,我们将为您提供有关反编译器支持的更多改进。此外,我们将展示如何创建没有原型的 Maven 项目以及一…...