深入挖掘C语言 ---- 文件操作

news2025/3/1 10:01:29

目录

  • 1. 文件的打开和关闭
    • 1.1 流和标准流
      • 1.1.1流
      • 1.1.2标准流
    • 1.2 文件指针
    • 1.3 文件的打开和关闭
  • 2. 顺序读写
  • 3. 随机读写
    • 3.1 fseek
    • 3.2 ftell
    • 3.3 rewind
  • 4. 读取结束判定


正文开始

1. 文件的打开和关闭

1.1 流和标准流

1.1.1流

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

C程序对文件, 画面, 键盘等的数据输入输出操作都是通过流操作的.

一般情况下, 我们想要向流里写数据, 或者从流中读取数据, 都是打开流, 然后操作.

1.1.2标准流

C语言程序在启动的时候. 默认打开了3个流:

  • stdin: 标准输入流, 在大多数的环境中从键盘输入, scanf函数就是从标准输入流中读取数据
  • stdout: 标准输出流, 大多数的环境中输出到显示器界面, printf函数就是将信息输出到标准输出流中.
  • stderr: 标准错误流, 大多数环境中输出到显示器界面

这是默认打开了这三个流, 我们使用scanf, printf等函数就可以直接进行输入输出操作的.
stdin, stdout, stderr 三个流的类型是: FILE* ,通常称为文件指针.
C语言中, 就是通过FILE* 的文件指针来维护流的各种操作.

1.2 文件指针

缓冲文件系统中, 关键的概念是"文件类型指针", 简称"文件指针".

每个被使用的文件都在内存中开辟了一个相应的文件信息区, 用来存放文件的相关信息(如文件名字, 文件状态以及文件当前的位置等). 这些信息是保存在一个结构体变量中的, 该结构体类型是由系统声明的, 取名FILE.

例如, 在VS2013编译环境提供的stdio.h头文件中有以下文件类型声明:

struct _iobuf {
	char* _ptr;
	int _cnt;
	char* _base;
	int _flag;
	int _file;
	int _charbuf;
	int _bufsiz;
	char* _tmpfname;
};
typedef struct _iobuf FILE;

不同的C编译器的FILE类型包含的内容不完全相同, 但是大同小异.

每当打开一个文件的时候. 系统会根据文件的情况自动创建一个FILE结构的变量, 并且填充其中的信息, 使用者不必关心细节.

⼀般都是通过⼀个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。

FILE* pf;//⽂件指针变量

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

在这里插入图片描述

1.3 文件的打开和关闭

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。

ANSIC规定使用 fopen 函数来打开文件, fclose 来关闭文件.

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

mode表示文件的打开模式,下面都是文件的打开模式:

在这里插入图片描述
在这里插入图片描述

/* fopen fclose example */
#include <stdio.h>
int main()
{
	FILE* pFile;
	//打开⽂件 
	pFile = fopen("myfile.txt", "w");
	//⽂件操作 
	if (pFile != NULL)
	{
		fputs("fopen example", pFile);
		//关闭⽂件 
		fclose(pFile);
	}
	return 0;
}

2. 顺序读写

在这里插入图片描述

上⾯说的适⽤于所有输⼊流⼀般指适⽤于标准输⼊流和其他输⼊流(如⽂件输⼊流);所有输出流⼀
般指适⽤于标准输出流和其他输出流(如⽂件输出流)。

3. 随机读写

3.1 fseek

根据⽂件指针的位置和偏移量来定位⽂件指针(⽂件内容的光标)。

其中,stream是一个指向文件的指针,offset是要移动的偏移量,origin是起始位置。起始位置可以是以下值之一:

SEEK_SET:从文件开头开始偏移
SEEK_CUR:从当前位置开始偏移
SEEK_END:从文件末尾开始偏移
fseek函数可以用来在文件中移动指针位置,以便读取或写入文件的不同部分。

int fseek ( FILE * stream, long int offset, int origin );

fseek函数的返回值是一个整数,用来表示函数是否执行成功。如果函数执行成功,则返回0;如果执行失败,则返回非0值,通常是-1。在实际使用中,我们可以根据fseek函数的返回值来判断文件指针位置是否成功移动。

/* fseek example */
#include <stdio.h>
int main()
{
	FILE* pFile;
	pFile = fopen("example.txt", "wb");
	fputs("This is an apple.", pFile);
	fseek(pFile, 9, SEEK_SET);
	fputs(" sam", pFile);
	fclose(pFile);
	return 0;
}

3.2 ftell

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

long int ftell ( FILE * stream );

ftell函数接受一个指向文件的指针作为参数,然后返回当前文件指针相对于文件起始位置的偏移量(以字节为单位)。通常,ftell函数常与fseek函数一起使用,用来确定文件指针的位置,然后再根据需要进行文件指针的移动或操作。

/* ftell example : getting size of a file */
#include <stdio.h>
int main()
{
	FILE* pFile;
	long size;
	pFile = fopen("myfile.txt", "rb");
	if (pFile == NULL)
		perror("Error opening file");
	else
	{
		fseek(pFile, 0, SEEK_END); // non-portable
		size = ftell(pFile);
		fclose(pFile);
		printf("Size of myfile.txt: %ld bytes.\n", size);
	}
	return 0;
}

3.3 rewind

让⽂件指针的位置回到⽂件的起始位置

void rewind ( FILE * stream );

rewind函数接受一个指向文件的指针作为参数,然后将该文件指针重新定位到文件的起始位置。这样可以方便重新读取文件内容或者进行其他操作。注意,rewind函数不返回任何值,因为它是一个void函数。

#include <stdio.h>
int main()
{
	int n;
	FILE* pFile;
	char buffer[27];

	pFile = fopen("myfile.txt", "w+");
	for (n = 'A'; n <= 'Z'; n++)
		fputc(n, pFile);
	rewind(pFile);

	fread(buffer, 1, 26, pFile);
	fclose(pFile);

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

4. 读取结束判定

  1. 文本文件:
    读取过程中不能用feof函数的返回值直接来判断文件是否结束
    feof的作用是: 当文件读取结束的时候, 判断是否读取结束的原因是否是: 文件末尾
  • fgetc判断是否为EOF
  • fgets判断是否为NULL

2.二进制文件的读取结束判断, 判断是否小于实际要读的个数
例如:

  • fread判断返回值是否小于实际要读的个数

文本文件举例:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	int c; // 注意:int,⾮char,要求处理EOF 
	FILE* fp = fopen("test.txt", "r");
	if (!fp) {
		perror("File opening failed");
		return EXIT_FAILURE;
	}
	//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOF 
	while ((c = fgetc(fp)) != EOF) // 标准C I/O读取⽂件循环 
	{
		putchar(c);
	}
	//判断是什么原因结束的 
	if (ferror(fp))
		puts("I/O error when reading");
	else if (feof(fp))
		puts("End of file reached successfully");

	fclose(fp);
}

二进制文件举例:

#include <stdio.h>

enum { SIZE = 5 };
int main(void)
{
	double a[SIZE] = { 1.,2.,3.,4.,5. };
	FILE* fp = fopen("test.bin", "wb"); // 必须⽤⼆进制模式 
	fwrite(a, sizeof * a, SIZE, fp); // 写 double 的数组 
	fclose(fp);

	double b[SIZE];
	fp = fopen("test.bin", "rb");
	size_t ret_code = fread(b, sizeof * b, SIZE, fp); // 读 double 的数组 
	if (ret_code == SIZE) {
		puts("Array read successfully, contents: ");
		for (int n = 0; n < SIZE; ++n)
			printf("%f ", b[n]);
		putchar('\n');
	}
	else { // error handling
		if (feof(fp))
			printf("Error reading test.bin: unexpected end of file\n");
		else if (ferror(fp)) {
			perror("Error reading test.bin");
		}
	}

	fclose(fp);
}


本文内容到此结束, 还请读者点赞关注

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

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

相关文章

小白也能看懂的BEV感知技术(二)

1. 引言 在自动驾驶的领域中&#xff0c;BEV&#xff08;Birds Eye View&#xff0c;鸟瞰图&#xff09;感知技术扮演着至关重要的角色。它允许自动驾驶车辆从上帝视角“看到”周围的环境&#xff0c;就像一只鸟从空中俯瞰地面一样。这项技术对于理解车辆周围的复杂场景至关重…

【Linux系统】地址空间 Linux内核进程调度队列

1.进程的地址空间 1.1 直接写代码&#xff0c;看现象 1 #include<stdio.h>2 #include<unistd.h>3 4 int g_val 100;5 6 int main()7 {8 int cnt 0;9 pid_t id fork();10 if(id 0)11 {12 while(1)13 {14 printf(&…

javaagent使用

Java Agent是什么&#xff1f; Java Agent是Java平台提供的一个强大工具&#xff0c;它可以在运行时修改或增强Java应用程序的行为。是在JDK1.5以后引入的&#xff0c;它能够在不影响正常编译的情况下修改字节码&#xff0c;相当于是在main方法执行之前的拦截器&#xff0c;也叫…

Python | Leetcode Python题解之第32题最长有效括号

题目&#xff1a; 题解&#xff1a; class Solution:def longestValidParentheses(self, s: str) -> int:stack[]maxL0nlen(s)tmp[0]*n #标记数组cur0for i in range(n):if s[i](:stack.append(i)else:if stack:jstack.pop()if s[j](:tmp[i],tmp[j]1,1 #匹配成…

【C++】:C++关键字,命名空间,输入输出,缺省参数

目录 一&#xff0c;C关键字(C98)二&#xff0c;命名空间2.1 命名冲突2.2 关键字namespace2.2.1 命名空间中可以定义变量/函数/类型2.2.2 命名空间可以嵌套2.2.3 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。 2.3 命名空间的使用2.3.1 指定…

多模态AnyGPT——整合图像、语音和文本多模态大规模语言模型算法原理与实践

概述 大规模语言模型在理解和生成人类语言方面具有非凡的能力&#xff0c;但迄今为止&#xff0c;它们的能力主要局限于文本处理。然而&#xff0c;现实世界是一个多模式的环境&#xff0c;信息通过视觉、听觉和触觉等多种感官进行交换。融入这种多样性是开发下一代系统的主要…

桥接模式【结构型模式C++】

1.概述 桥接模式是一种结构型设计模式&#xff0c;是用于把抽象化与实现化解耦&#xff0c;使得二者可以独立变化。这种类型的设计模式属于结构型模式&#xff0c;它通过提供抽象化和实现化之间的桥接结构&#xff0c;来实现二者的解耦。 这种模式涉及到一个作为桥接的接口&am…

高斯溅射融合之路(一)- webgl渲染3d gaussian splatting

大家好&#xff0c;我是山海鲸的技术负责人。之前已经写了一个GIS融合系列。其实CesiumJS的整合有相当的难度&#xff0c;同时也有很多方面的工作&#xff0c;很难在几篇文章内写完&#xff0c;整个山海鲸团队也是投入了接近两年的时间&#xff0c;才把周边整套工具链进行了完善…

算法复杂度分析笔记

基本定义间的关系 算法介绍 算法分析 时间复杂度 用数量级刻画&#xff1a;忽略所有低次幂项和系数 eg1: eg2: eg3: eg4: 小结 空间复杂度 eg: 总结

Vue3从入门到实践:深度了解新组件

1.Teleport 概念&#xff1a;Teleport&#xff08;传送门&#xff09;是一个新的特性&#xff0c;用于在DOM中的任意位置渲染组件。它允许你将组件的内容渲染到DOM中的另一个位置&#xff0c;而不受组件层次结构的限制。 下面举出例子解释&#xff1a; 1.新建App.vue文件作…

YOLOv9改进策略 | Neck篇 | 2024.1最新MFDS-DETR的HS-FPN改进特征融合层(轻量化Neck、全网独家首发)

一、本文介绍 本文给大家带来的改进机制是最近这几天最新发布的改进机制MFDS-DETR提出的一种HS-FPN结构&#xff0c;其是一种为白细胞检测设计的网络结构&#xff0c;主要用于解决白细胞数据集中的多尺度挑战。它的基本原理包括两个关键部分&#xff1a;特征选择模块和特征融合…

vue快速入门(三十一)vscod开发vue需要下载的插件

步骤很详细&#xff0c;直接上教程 上一篇 暂时就这两样足矣&#xff0c;有新的以后再更新&#xff08;别下载太多&#xff0c;可能会冲突&#xff09; 测试一下&#xff1a; 提示功能&#xff1a; 代码补全功能&#xff1a;

基于弹簧鞘复合纱和迁移学习算法的可穿戴人体重构和智能试衣系统

研究背景 在信息时代和元宇宙的背景下&#xff0c;虚拟服装设计对满足服装行业的个性化需求至关重要。与传统方法不同&#xff0c;虚拟试衣节省时间、方便客户&#xff0c;并提供多样化的款式。准确得测量人体围度并重构出人体的模型是虚拟试衣的关键。为了实现动态人体重构&a…

第Y7周:训练自己的数据集

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制&#x1f680; 文章来源&#xff1a;K同学的学习圈子 目录 一、下载YOLOv8 二、配置环境 三、准备工作 四、运行 出现报错&#xff1a;…

《QT实用小工具·三十一》基于QT开发的访客管理平台demo2

1、概述 源码放在文章末尾 该项目为访客管理平台demo&#xff0c;包含主界面、系统设置、警情查询、调试帮助、用户退出功能。 项目部分代码如下&#xff1a; #pragma execution_character_set("utf-8")#include "frmmain.h" #include "ui_frmmain…

使用不锈钢微型导轨的优势!

微型导轨是一种专门用于在紧凑空间内执行高精度的机器运动控制的导轨设备。其特点是尺寸小、精确度高、刚性好、平稳性好以及使用寿命长。微型导轨的材质种类多样&#xff0c;一般包括钢、不锈钢、铝合金等。目前来说&#xff0c;不锈钢材质的使用率最为频繁&#xff0c;那么使…

python中中英文打印对齐解决方案

在python中&#xff0c;有时候会出现中英文混合输出的情形&#xff0c;但是由于中文默认是全角格式&#xff08;一个中文字符占用两个字符宽度&#xff09;&#xff0c;这会对python原生的print函数带来一些障碍。尤其是用户用print对齐输出的时候&#xff0c;这种差异会导致文…

揭秘网红主播美颜工具:探秘美颜SDK的技术奥秘

在如今的网络直播平台上&#xff0c;越来越多的主播通过美颜工具来提升自己的形象&#xff0c;吸引更多的粉丝和观众。美颜技术的不断发展使得主播们能够在镜头前展现出更加完美的容颜&#xff0c;让观众眼前一亮。 一、美颜SDK的概念 美颜SDK&#xff0c;即美颜软件开发工具…

Bert语言大模型基础

一、Bert整体模型架构 基础架构是transformer的encoder部分&#xff0c;bert使用多个encoder堆叠在一起。 主要分为三个部分&#xff1a;1、输入部分 2、注意力机制 3、前馈神经网络 bertbase使用12层encoder堆叠在一起&#xff0c;6个encoder堆叠在一起组成编码端&#xf…

存储过程的使用(一)

目录 不带参数的存储过程 创建一个存储过程&#xff0c;向数据表 dept 中插入一条记录 带 IN 参数的存储过程 在存储过程中接受来自外部的数值&#xff0c;在存储过程中判断该数值是否大于零并显示 输入一个编号&#xff0c;查询数据表emp中是否有这个编号&#xff0c;如果…