C语言之详细讲解文件操作(抓住文件操作的奥秘)

什么是文件

与普通文件载体不同,文件是以硬盘为载体存储在计算机上的信息集合,文件可以是文本文档、图片、程序等等。文件通常具有点+三个字母的文件扩展名,用于指示文件类型(例如,图片文件常常以KPEG格式保存并且文件扩展名为.jpg)。

将数据放入文件中,相比代码程序中堆栈上的数据,其优点在于可以随时做到需要时添加、舍弃时删除,数据可以持久化。

文件类型:

一般分为:程序文件与数据文件。

程序文件:

包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)。

数据文件:

文件的内容不一定是程序,而是程序运行中的读取的数据。本章讨论的是数据文件。


文件的使用

在了解文件怎样使用前,我们先要了解流与标准流的概念

程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输入输出操作各不相同,为了方便程序员对各种设备进行方便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着字符的河。

这样程序员在输入输出数据时不需要关心外部设备了,只需要将数据与流相连,C语言底层已经将流向不同外部设备的输入和输出实现好了,不需要我们关心。

我们只需要从流里读取数据,向流里写数据。

标准流


那为什么我们从键盘输入数据,向屏幕上输出数据,并没有打开流呢?

那是因为C语言程序在启动时已经将标准流(standard stream)准备好了。

默认打开了3个流:

stdin-标准输入流,在大多数的环境中从键盘输入,scanf函数就是从stdin-标准输入流(键盘)中读取数据。

stdout-标准输出流,大多数的环境中输出至显示器界面,printf函数就是将信息输出到stdout-标准输出流(屏幕)中。
stderr-标准错误流,大多数环境中输出到显示器界面。

stdin、 stdout、 stderr 三个流的类型是: FILE*,通常称为文件指针。
C语言中,就是通过 FILE*的文件指针来维护流的各种操作的。

文件的操作

文件操作分为三步:打开文件(fopen)、读取或写入文件、关闭文件(fclose)。

文件指针

缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名 字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系 统声明的,取名FILE.
FILE*pf;//文件指针变量pf

定义一个指针变量指向FILE类型数据,可以使pf指向某个文件的文件信息区(是一个结构体变 量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够间接找到与它关联的文件

文件的打开与关闭

  文件读写之前应该先打开文件,使用结束后应该关闭文件。
ANSIC 规定使用 fopen 函数来打开文件, fclose 函数来关闭文件。  

在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指
针和文件的关系。

fopen() —— 打开文件;
FILE * fopen ( const char * filename, const char * mode );
fclose() —— 关闭文件;
int fclose ( FILE * stream );

例:

#include<stdio.h>
#include<assert.h>

int main() {

	FILE* pr = fopen("test.txt","w");
	//当没有文件时读取,fopen输出NULL
	//当没有文件写入时,会自动创建文件
	assert(pr);
	//这里使用assert断言,以防pr为空,也可以使用perror函数
	for (char ch = 'a'; ch <= 'z'; ch++) {
		fputc(ch, pr);//fputc函数将字符ch存入pr文件中
	}
	fclose(pr);
	return 0;
}

文件的使用方式:

按常用序:

文件的顺序读写:

1.写入一个字符

fgetc(字符c,文件指针);

2.读取一个字符

fputc(文件指针);
//每一次读取光标回向后移动一位
例:test.txt文件里面:abcdefg
char ch=fputc(pr);
printf(%c,ch);//输出为a;
char ch=fputc(pr);
printf(%c,ch);//输出为b;

3.写入一个字符串

fgets("hello,world",文件指针);
//每次的写入会导致数据的覆盖,在原先的数据后继续添加,需要使用a(追加);

4.读取指定长度的数据(读取数组)

char arr[10]={0};
fgets(arr,5,文件指针);//将所读取的数据存入arr数组中

5.读取结构体指定数据(fprintf);

#include<stdio.h>

typedef struct S//typdef,以便更好的创建结构体变量
{
	char name[10];
	int age;

}S1;

int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf != NULL)//也可用assert函数判断是否为空
	{
		S1 s1 = { "zhangsan", 18 };//创建变量s1
		fprintf(pf, "%s %d\n", s1.name, s1.age);

		fclose(pf);
		pf = NULL;
	}
	return 0;
}

文件的随机读写

fseek函数

fseek - C++ 参考 (cplusplus.com)

ftell - C++ Reference

ferror - C++ Reference

int fseek ( FILE * stream, long int offset, int origin );
                          流                  偏移量           起始位置
流:指向标识流的 FILE 对象的指针。
偏移量:二进制文件:要从源偏移的字节数。文本文件:零或 ftell 返回的值。

如果成功,该函数将返回零。
否则,它将返回非零值。
如果发生读取或写入错误,则设置错误指示符 (ferror)。

三种定位指针

#include<stdio.h>

int main()
{
	FILE* pFile;
	pFile = fopen("test.txt", "r");
	//fputs("This is an apple.", pFile);
	
    fseek(pFile,2, SEEK_SET);//从起始位置的第二个偏移量
	int ch = fgetc(pFile);
	printf("%c", ch);

	fclose(pFile);
	return 0;
}

注意:

ftell函数

返回文件指针相对起始位置的偏移量

long int ftell ( FILE * stream );//注:返回为long int类型
#include <stdio.h>
int main()
{
	int n;
	FILE* pFile;
	char buffer[27];

	pFile = fopen("test.txt", "w+");
	for (n = 'A'; n <= 'Z'; n++)
		fputc(n, pFile);//向文本中输入字符
	rewind(pFile);//让文件指针回到起始位置

	fread(buffer, 1, 26, pFile);//读取1到26个数据
	fclose(pFile);

	buffer[26] = '\0';
	printf(buffer);//验证
	return 0;
}

feof函数(文件读取结束的判定)

feof - C++ 参考 (cplusplus.com)

文本文件:

  • fgetc 判断是否为 EOF .
  • fgets 判断返回值是否为 NULL
二进制文件:

        都是使用 fread() 读取,要判断其返回值与指定读取个数的大小,如果小于实际要读的个数,就说明发生读取异常,如果等于实际要读的个数,就说明是因读取成功而结束;

对于读取异常的判断,我们考虑判断 ferror() 函数的返回值:

若ferrror()为真——异常读取而结束;
若feof()为真——正常读取到尾而结束;

二进制文件和文本文件
我们知道数据在内存中是以二进制形式存储的,对于文件而言:如果不加转换直接输出到外存就是二进制文件;如果要在外存上以ASCII码形式存储,就需要提前转换最后以ASCII码值形式存储的文件就是文本文件。

对于字符,一律使用ASCII码形式存储,但对于数值型数据,即可以使用ASCII码存储也可以使用二进制形式存储。


oi!点个赞走吧!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JDBC连接MySQL8 SSL

1.创建用户并指定ssl连接 grant all on . to test% identified by imooc require SSL(X509); 2.查看是否使用ssl SELECT ssl_type From mysql.user Where user"test" 3.配置用户必须使用ssl ALTER USER test% REQUIRE SSL(X509); FLUSH PRIVILEGES; 注意&#xff…

Ollamallama

Olllama 直接下载ollama程序&#xff0c;安装后可在cmd里直接运行大模型&#xff1b; llama 3 meta 开源的最新llama大模型&#xff1b; 下载运行 1 ollama ollama run llama3 2 github 下载仓库&#xff0c;需要linux环境&#xff0c;windows可使用wsl&#xff1b; 接…

mac如何打开exe文件?如何mac运行exe文件 如何在Mac上打开/修复/恢复DMG文件

在macOS系统中&#xff0c;无法直接运行Windows系统中的.exe文件&#xff0c;因为macOS和Windows使用的是不同的操作系统。然而&#xff0c;有时我们仍然需要运行.exe文件&#xff0c;比如某些软件只有Windows版本&#xff0c;或者我们需要在macOS系统中运行Windows程序。 虽然…

【MATLAB源码-第200期】基于matlab的鸡群优化算法(CSO)机器人栅格路径规划,输出做短路径图和适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 鸡群优化算法&#xff08;Chicken Swarm Optimization&#xff0c;简称CSO&#xff09;是一种启发式搜索算法&#xff0c;它的设计灵感来源于鸡群的社会行为。这种算法由Xian-bing Meng等人于2014年提出&#xff0c;旨在解决…

STM32 工程移植 LVGL:一步一步完成

STM32 工程移植 LVGL&#xff1a;一步一步完成 LVGL&#xff0c;作为一款强大且灵活的开源图形库&#xff0c;专为嵌入式系统GUI设计而生&#xff0c;极大地简化了开发者在创建美观用户界面时的工作。作为一名初学者&#xff0c;小编正逐步深入探索LVGL的奥秘&#xff0c;并决…

Java面试八股之强软弱虚引用的概念及区别

Java中强软弱虚引用的概念及区别 在Java中&#xff0c;强引用、软引用、弱引用和虚引用是四种不同类型的引用&#xff0c;它们在对象生命周期管理、垃圾收集&#xff08;Garbage Collection, GC&#xff09;以及内存管理方面有着不同的行为和用途。以下是它们的概念和主要区别…

LeetCode 543.二叉树的直径

题目描述 给你一棵二叉树的根节点&#xff0c;返回该树的 直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。 两节点之间路径的 长度 由它们之间边数表示。 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,4,5]…

云计算技术概述_1.云计算相关概念

1.关于IBM“蓝云&#xff08;Blue Cloud&#xff09;”计划 IBM 推出的“蓝云&#xff08;Blue Cloud&#xff09;”计划为客户带来即可使用的云计算(Cloud Computing)。它包括一系列的云计算产品&#xff0c;使计算不仅仅局限在本地机器或远程Server Farms&#…

曹操出行冲刺港交所上市:2023年收入突破100亿元,规模效应显现

近日&#xff0c;曹操出行有限公司&#xff08;下称“曹操出行”&#xff09;向港交所递交上市申请&#xff0c;华泰国际、农银国际、广发证券&#xff08;香港&#xff09;担任其联席保荐人。 据招股书介绍&#xff0c;曹操出行由吉利控股集团于2015年孵化成立&#xff0c;使…

aardio封装库) 微软开源的js引擎(ChakraCore)

前言 做爬虫肯定少不了JavaScript引擎的使用&#xff0c;比如在Python中现在一般用pyexecjs2来执行JavaScript代码&#xff0c;另外还有一些其他执行JavaScript的库&#xff1a; https://github.com/eight04/node_vm2: rpc调用nodejs&#xff0c;需要安装nodehttps://github.…

第二篇【传奇开心果系列】Python深度学习库技术点案例示例:深度解读深度学习在语音助手方面的应用

传奇开心果博文系列 系列博文目录Python深度学习库技术点案例示例系列 博文目录前言一、深度学习在语音助手方面的应用介绍二、语音识别示例代码三、语义理解示例代码四、对话生成示例代码五、个性化服务示例代码六、多模态交互示例代码七、情感识别示例代码八、知识点归纳 系列…

Stylus深度解析:开发效率提升秘籍(AI写作)

首先&#xff0c;这篇文章是基于笔尖AI写作进行文章创作的&#xff0c;喜欢的宝子&#xff0c;也可以去体验下&#xff0c;解放双手&#xff0c;上班直接摸鱼~ 按照惯例&#xff0c;先介绍下这款笔尖AI写作&#xff0c;宝子也可以直接下滑跳过看正文~ 笔尖Ai写作&#xff1a;…

Git学习笔记(五)IDEA使用Git

在前面几篇文章中&#xff0c;我们已经介绍了git的基础知识&#xff0c;知道了其主要作用是用来进行代码的版本管理&#xff1b;并且已经介绍了Git操作的常用命令。在日常的开发环境下&#xff0c;除了通过Bash命令行来操作Git之外&#xff0c;我们另外一种常用的操作方式则是直…

专注 APT 攻击与防御—工具介绍-the-backdoor-factory

工具介绍 the-backdoor-factory 项目地址&#xff1a;GitHub - secretsquirrel/the-backdoor-factory: Patch PE, ELF, Mach-O binaries with shellcode new version in development, available only to sponsors 原理 可执行二进制文件中有大量的 00&#xff0c;这些 00 是…

ACP科普:MoSCoW优先排序法则

MoSCoW 优先级排序法&#xff0c;是项目管理定义范围、确定功能质量、变更管理中常用的工具法则&#xff0c;以便用户、项目主管、项目经理、供应商对纳入项目中的每个需求交付的重要性和紧急性达成共识。M—o-S-C—o-W&#xff0c;是四个优先级别的首字母的缩写&#xff0c;再…

OJ1——轮转数组,消失的数字

题目1——轮转数组 题目来源. - 力扣&#xff08;LeetCode&#xff09; 轮转&#xff08;或称为旋转&#xff09;数组是一种常见的算法问题&#xff0c;通常指的是将数组中的元素向右或向左移动一定位置&#xff0c;使得数组的元素重新排列。 以下是一个简单的思路&#xff0…

基于ssm+vue+Mysql的药源购物网站

开发语言&#xff1a;Java框架&#xff1a;ssmJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;Maven3.…

【C语言/数据结构】经典链表OJ习题~第二期——链中寻环

&#x1f388;&#x1f388;&#x1f388;欢迎采访小残风的博客主页&#xff1a;残风也想永存-CSDN博客&#x1f388;&#x1f388;&#x1f388; &#x1f388;&#x1f388;&#x1f388;本人码云 链接&#xff1a;残风也想永存 (FSRMWK) - Gitee.com&#x1f388;&#x1f…

Unity LensFlare 入门

概述 在项目的制作过程中&#xff0c;太阳光的使用一定是不可缺少的部分&#xff0c;但是如果想实现真实太阳光眼睛看到的镜头炫光效果&#xff0c;那这部分的内容一定不要错过喔&#xff0c;接下来让我们来学习这部分的内容吧&#xff01; Hale(光环效果) Color&#xff1a;…

Rust Rocket创建第一个hello world的Web程序 Rust Rocket开发常用网址和Rust常用命令

一、Rust Rocket简介 Rust Rocket 是一个用 Rust 语言编写的 Web 应用框架&#xff0c;它结合了 Rust 的安全性和性能优势&#xff0c;以及 Web 开发的便利性。以下是 Rust Rocket 框架的一些优点&#xff1a; 安全性&#xff1a;Rust 是一种注重安全性的编程语言&#xff0c;…