【C语言】详解文件与文件操作

news2024/11/28 10:53:44

1.什么是文件

文件是记录在外存上的相关信息的命名组合,但是在程序设计中,我们⼀般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。

1.1程序文件

程序文件包括:

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

1.2数据文件

文件的内容不⼀定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。

1.3文件名

⼀个文件要有⼀个唯一的文件标识,以便用户识别和引用
文件名包含3部分:文件路径+文件名主干+文件后缀
例如:

 c:\code\test.txt

为了方便起见,文件标识常被称为文件名。

2.为什么要使用文件

如果没有文件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运行程序,是看不到上次程序的数据的,如果要将数据进行持久化的保存,我们可以使用文件

3.二进制文件和文本文件

根据数据的组织形式,数据文件可以分为文本文件二进制文件

  • 数据在内存中以二进制的形式存储,如果不加转换输出到外存,就是二进制文件
  • 如果要求在外存上以ASCII码的形式存储,则需要在存储前转换,以ASCII字符的形式存储的文件就是文本文件

3.1一个数据在内存中是如何存储

字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储,如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节(VS2019测试)
在这里插入图片描述

4.文件的打开和关闭

4.1流和标准流

4.1.1流

我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输⼊输出操作各不相同,为了⽅便程序员对各种设备进行方便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着字符的河。
C程序针对文件、画面、键盘等的数据输入输出操作都是通过流操作的
一般情况下,我们要想向流里写数据,或者从流中读取数据,都是要打开流,然后操作。

4.1.2标准流

那为什么我们从键盘输入数据,向屏幕上输出数据,并没有打开流呢?
那是因为C语言程序在启动的时候,默认打开了3个流:

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

这是默认打开了这三个流,我们使用scanf、printf等函数就可以直接进行输入输出操作的。

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

4.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*的指针变量:

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

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

4.3文件的打开和关闭

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件
在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。
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;
}

5.文件的顺序读写

顺序读写函数介绍
在这里插入图片描述
以上说的适用于所有输入流一般指适用于标准输入流和其他输入流(如文件输入流)
所有输出流一般指适用于标准输出流和其他输出流(如文件输出流)

6.文件的随机读写

6.1 fseek

根据文件指针的位置和偏移量来定位文件指针

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

举个例子:

/* 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;
}

6.2 ftell

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

long int ftell ( FILE * stream );

举个例子:

/* 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;
}

6.3 rewind

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

void rewind ( FILE * stream );

举个例子:

/* rewind example */
#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;
}

7.文件读取结束的判定

7.1 feof

牢记:在文件读取过程中,不能用feof函数的返回值直接来判断文件的是否结束
feof 的作用:当文件读取结束的时候,判断是读取结束的原因是否是:遇到文件尾结束

  1. 文本文件读取是否结束,判断返回值是否为 EOF(fgetc),或者 NULL(fgets)

例如:

  • fgetc 判断是否为 EOF
  • fgets 判断返回值是否为 NULL
  1. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数

例如:

  • 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);
}

8.文件缓冲区

ANSIC标准采用”缓冲文件系统“处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的
因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。
如果不做,可能导致读写文件的问题。

—————————————————————————————

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

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

相关文章

Pytorch基础知识点复习

文章目录 并行计算单卡训练多卡训练单机多卡DP多机多卡DDPDP 与 DDP 的优缺点 PyTorch的主要组成模块Pytorch的主要组成模块包括那些呢&#xff1f;Dataset和DataLoader的作用是什么&#xff0c;我们如何构建自己的Dataset和DataLoader&#xff1f;神经网络的一般构造方法&…

头部姿态估计算法原理

人脸检测 文章目录 人脸检测一、前言二、原理三、代码实现 一、前言 头部姿态估计是通过一幅面部图像来获得头部的姿态角. 在3D空间中&#xff0c;表示物体的旋转可以由三个欧拉角(Euler Angle)来表示&#xff1a;分别计算 pitch(围绕X轴旋转)&#xff0c;yaw(围绕Y轴旋转) 和…

网络新手必读!CentOS 7系统IP配置与防火墙管理攻略

前言 掌握CentOS 7系统的网络配置技能&#xff0c;从IP地址、子网掩码、DNS到防火墙&#xff0c;一篇文章全搞定&#xff01;无论你是网络新手还是寻求深入了解的高手&#xff0c;这篇文章都为你提供了简单易懂的配置指南&#xff0c;助你轻松驾驭系统网络。摆脱繁琐的配置困扰…

C# 图解教程 第5版 —— 第23章 异常

文章目录 23.1 什么是异常23.2 try 语句23.3 异常类23.4 catch 子句23.5 异常过滤器23.6 catch 子句段23.7 finally 块23.8 为异常寻找处理程序23.9 进一步搜索23.9.1 一般法则23.9.2 搜索调用栈的示例&#xff08;*&#xff09; 23.10 抛出异常23.11 不带异常对象的抛出23.12 …

基于变换域的模版匹配

模板匹配原理 图像的空间域与其他域之间的变换&#xff0c;如傅里叶变换&#xff0c;小波变换&#xff0c;轮廓波变换&#xff0c;剪切波变换等&#xff0c;实际上是图像在其他坐标领域中的表现。在空间域中&#xff0c;图像的信息是像素值和坐标位置&#xff1b;在其他域中&a…

快速上手!LLaMa-Factory最新微调实践,轻松实现专属大模型

1.为什么要对Yuan2.0做微调&#xff1f; Yuan2.0&#xff08;https://huggingface.co/IEITYuan&#xff09;是浪潮信息发布的新一代基础语言大模型&#xff0c;该模型拥有优异的数学、代码能力。自发布以来&#xff0c;Yuan2.0已经受到了业界广泛的关注。当前Yuan2.0已经开源…

day19【LeetCode力扣】160.相交链表

day19【LeetCode力扣】160.相交链表 1.题目描述 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交**&#xff1a;** 题目数据 保证 整个链…

基于MATLAB计算无线通信覆盖(一)环境准备

一、环境 MATLAB 2022b 注&#xff1a;开始仿真前需部署地理坐标区和地理图&#xff0c;最好采用第三种&#xff0c;直接把底图数据下载到本地&#xff0c;防止连接不上网络时只能显示darkwater的底图。 可用于地理坐标区和地理图的底图如下表所示 二、下载底图并安装 工具&…

Intel开发环境Quartus、Eclipse与WSL的安装

PC &#xff1a;win10 64bit 安装顺序&#xff1a;先安装Quartus 21.4&#xff0c;接着Eclipse或者WSL&#xff08;Windows Subsystem for Linux&#xff09;&#xff0c;Eclipse与WSL的安装不分先后。 为什么要安装Eclipse&#xff1f; 因为Eclipse可以开发基于Nios II的C/…

RabbitMQ使用篇

☆* o(≧▽≦)o *☆嗨~我是小奥&#x1f379; &#x1f4c4;&#x1f4c4;&#x1f4c4;个人博客&#xff1a;小奥的博客 &#x1f4c4;&#x1f4c4;&#x1f4c4;CSDN&#xff1a;个人CSDN &#x1f4d9;&#x1f4d9;&#x1f4d9;Github&#xff1a;传送门 &#x1f4c5;&a…

CTF CRYPTO 密码学-1

题目名称&#xff1a;enc 题目描述&#xff1a; 压缩包中含两个文件&#xff1a;一个秘钥d.dec&#xff0c;一个密文flag.enc 解题过程&#xff1a; Step1&#xff1a;这题是一个解密他题目&#xff0c;尝试openssl去ras解密 工具简介 在Kali Linux系统中&#xff0c;openss…

交友系统程序开发,前后端源码交付,允许二开,UI配色新颖,APP小程序H5随心搭配!

在开发设计与测试阶段&#xff0c;主要包括了程序开发、测试和上线运营等环节。根据产品经理确定的功能需求&#xff0c;开发团队开始进行具体的编程和开发工作。这个过程中需要考虑到不同设备、不同系统和不同版本的需求&#xff0c;确保软件可以在不同平台上稳定运行。 测试是…

通过指令反向翻译进行自我对齐

1、写作动机&#xff1a; 对齐大型语言模型以执行指导性任务通常需要在大量人工标注的指令或偏好信息上进行微调&#xff0c;然而&#xff0c;使用此类高质量数据对指令遵循任务进行标注是难以扩展的。 2、贡献&#xff1a; 提出了一种可扩展的方法&#xff0c;通过自动标注…

【问题记录】使用命令语句从kaggle中下载数据集

从Kaggle中下载Tusimple数据集 1.服务器环境中安装kaggle 使用命令&#xff1a;pip install kaggle 2.复制下载API 具体命令如下&#xff1a; kaggle datasets download -d manideep1108/tusimple3.配置kaggle.json文件 如果直接使用命令会报错&#xff1a; root:~# kagg…

使用dbever连接 hsqldb

完整的url为 jdbc:hsqldb:hsql://ip:端口/别名 注意&#xff0c;hsqldb跟随应用启动和停止&#xff0c;所以当应用断点时&#xff0c;hsqldb也会连接不上导致查询数据失败&#xff0c;可以断点前进一步

IOS-相机权限申请-Swift

配置描述 在Info.plist文件中&#xff0c;新建一个键值对Privacy - Camera Usage Description&#xff08;或者NSCameraUsageDescription&#xff09;&#xff0c;值为申请描述说明&#xff0c;自定义的 申请 然后在需要申请的文件中导入AVFoundation import AVFoundation…

时间序列预测 — BiLSTM-Attention实现单变量负荷预测(Tensorflow)

专栏链接&#xff1a;https://blog.csdn.net/qq_41921826/category_12495091.html 专栏内容 ​ 所有文章提供源代码、数据集、效果可视化 ​ 文章多次上领域内容榜、每日必看榜单、全站综合热榜 ​ ​ ​ ​ ​ ​ ​ 时间序列预测存在的问题 ​ 现有的大量方法没有真正的预测未…

高校学生选课系统源码开发方案

一、项目背景与目标 &#xff08;一&#xff09;项目背景 随着高校教育的发展&#xff0c;学生选课系统成为了高校管理中不可或缺的一部分。传统的手工选课方式存在着效率低下、易出错等问题&#xff0c;因此需要开发一款高效、便捷的高校学生选课系统。 &#xff08;二&…

C++make_pair,你真的懂了吗?

其实写这篇文章我还是很忐忑的&#xff0c;因为用C也写了快一年了&#xff0c;平时代码量个人认为还可以&#xff0c;但是最近两天频繁犯错&#xff0c;下面先说说我写的错误吧&#xff01; 我们都知道make_pair返回的是一个pair类型的函数&#xff0c;而pair这个键值对它又是…

MATLAB中simulink中scope同时显示两个输入信号

在使用scope时&#xff0c;需要两个输入信号的设置方法 1.点开scope图标 2 点击设置按钮&#xff0c; 然后弹出configuration properties&#xff1a;scope配置图&#xff0c;在Main选项下&#xff0c;在Number of input ports&#xff1a;1这里面更改数字&#xff0c;需要几…