C【文件操作】

news2024/10/7 18:23:54

1. 什么是文件

磁盘上的文件是文件。 但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。

1.1 程序文件

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

1.2 数据文件

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

1.3 文件名

1.4 文件缓冲区

2. 文件的打开和关闭

2 .1 文件指针:FILE

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

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

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

下面我们可以创建一个FILE*的指针变量:

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

3.2 文件的打开(fopen)和关闭(fclose)

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

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

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

//打开文件

FILE * fopen ( const char * filename, const char * mode );

//关闭文件

int fclose ( FILE * stream ); 比特

#include <errno.h>
#include <string.h>

int main()
{
	//打开文件test.txt
	//相对路径
	//.. 表示上一级路径
	//.  表示当前路径
	//fopen("../../test.txt", "r")
	//fopen("test.txt", "r");
	
	//绝对路径的写法【添加转义字符】
	//fopen("C:\\2020_code\\84班\\test_5_6\\test_5_6\\test.txt", "r");

	FILE* pf = fopen("test.txt", "w");
	if(pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return 0;
	}
	//打开成功
	//读文件

	//关闭文件
	fclose(pf);
	pf = NULL;

	return 0;
}

3. 文件的顺序读写

3.1 fputc:写入文件

操作一行

int main()
{
	FILE* pfWrite = fopen("TEST.txt", "w");
	if(pfWrite == NULL)
	{
		printf("%s\n", strerror(errno));
		return 0;
	}
	//写文件
	fputc('b', pfWrite);
	fputc('i', pfWrite);
	fputc('t', pfWrite);
	
	//关闭文件
	fclose(pfWrite);
	pfWrite = NULL;

	return 0;
}

3.2 fgetc():读取文件

操作一行

int main()
{
	FILE* pfRead = fopen("test.txt", "r");
	if(pfRead == NULL)
	{
		printf("%s\n", strerror(errno));
		return 0;
	}
	//读文件
	printf("%c", fgetc(pfRead));//b
	printf("%c", fgetc(pfRead));//i
	printf("%c", fgetc(pfRead));//t

	//关闭文件
	fclose(pfRead);
	pfRead = NULL;

	return 0;
}

3.3 输入/输出设备

从键盘输入
输出到屏幕.
键盘&屏幕都是外部设备【默认打开的】

键盘-标准输入设备- stdin
屏幕-标准输出设备- stdout
是一个程序默认打开的两个流设备

stdin FILE*
stdout FILE*
stderr FILE*

int main()
{
	int ch = fgetc(stdin);
	fputc(ch, stdout);

	return 0;
}

3.4 fgets():读取文件存储到指定位置

操作多行

int main()
{
	char buf[1024] = { 0 };

	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		return 0;
	}
	//读文件
	//表示从pf输入流中读取1024个字节到buf中
	fgets(buf, 1024, pf);
	printf("%s", buf);//bit

	return 0;
}

3.5 fputs()

要手动换行

int main()
{
	char buf[1024] = { 0 };

	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		return 0;
	}
	//写文件
	fputs("hello\n", pf);
	fputs("world\n", pf);


	fclose(pf);
	pf = NULL;

	return 0;
}

3.6 fputs()与fgets()

int main()
{
	//从键盘读取一行文本信息
	//char buf[1024] = {0};
	fgets(buf, 1024, stdin);//从标准输入流读取
	fputs(buf, stdout);//输出到标准输出流

	//gets(buf);
	//puts(buf);

	return 0;
}

3.7 puts()

会自动换行

3.8 fprintf()

struct S
{
	int n;
	float score;
	char arr[10];
};

int main()
{
	struct S s = { 100, 3.14f, "bit" };
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		return 0;
	}
	//格式化的形式写文件
	fprintf(pf, "%d %f %s", s.n, s.score, s.arr);

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

3.9 fscanf()

struct S
{
	int n;
	float score;
	char arr[10];
};

int main()
{
	struct S s = {0};

	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		return 0;
	}
	//格式化的输入数据
	fscanf(pf, "%d %f %s", &(s.n), &(s.score), s.arr);
	printf("%d %f %s\n", s.n, s.score, s.arr);

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

3.10 fscanf()和fprintf()

struct S
{
	int n;
	float score;
	char arr[10];
};

int main()
{
	struct S s = { 0 };

	fscanf(stdin, "%d %f %s", &(s.n), &(s.score), s.arr);
	fprintf(stdout, "%d %.2f %s", s.n, s.score, s.arr);

	return 0;
}

 

3.11 面试题

int main()
{
	struct S s = { 100, 3.14f, "abcdef" };
	struct S tmp = {0};
	char buf[1024] = { 0 };
	//把格式化的数据转换成字符串存储到buf
	sprintf(buf, "%d %f %s", s.n, s.score, s.arr);
	//printf("%s\n", buf);
	//从buf中读取格式化的数据到tmp中
	sscanf(buf, "%d %f %s", &(tmp.n), &(tmp.score), tmp.arr);

	printf("%d %f %s\n", tmp.n, tmp.score, tmp.arr);

	return 0;
}

3.12 fwrite():写入二进制

//fwrite:将数据以二进制的形式写入
int main()
{
	struct S s = { "张三", 20, 55.6 };

	FILE* pf = fopen("test.txt", "rb");
	if (pf == NULL)
	{
		return 0;
	}
	//二进制的形式都文件
	//表示将s中的数据写入到pf中
	fwrite(&s, sizeof(struct S), 1, pf);
	printf("%s %d %lf\n", &s.name, &s.age, &s.score);

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

3.13 fread:通过二进制的方式读出数据

//fread:通过二进制的方式输出数据
int main()
{
	struct S tmp = { 0 };

	FILE* pf = fopen("test.txt", "rb");
	if (pf == NULL)
	{
		return 0;
	}
	//二进制的形式都文件
	//表示将pf中的数据写到tmp中
	fread(&tmp, sizeof(struct S), 1, pf);
	printf("%s %d %lf\n", tmp.name, tmp.age, tmp.score);

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

4. 文件的随机读写

4 .1 fseek

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

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

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		return 0;
	}
	//1.定位文件指针
	//fseek(要读取的文件,移动的字节数,起始位置)
	//SEEK_END:表示向前移动2个位置
	fseek(pf, -2, SEEK_END);
	//2.读取文件
	int ch = fgetc(pf);
	printf("%c\n", ch);

	fclose(pf);
	pf = NULL;

	return 0;
}

4.2 ftell

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

long int ftell ( FILE * stream );
//ftell:返回文件指针相对于起始位置的偏移量
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		return 0;
	}
	//2.读取文件
	int post = ftell(pf);
	printf("%d\n", post);//打开默认地址为0

	fclose(pf);
	pf = NULL;

	return 0;
}
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		return 0;
	}
	//此时读取一个字符,则表示跳过第一个字符
	fgetc(pf);
	//2.读取文件
	int post = ftell(pf);
	printf("%d\n", post);//故此时输出为1

	fclose(pf);
	pf = NULL;

	return 0;
}

4.3 rewind

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

void rewind ( FILE * stream );
//rewind:回到文件的起始位置
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		return 0;
	}
	int ch = fgetc(pf);
	printf("%c\n", ch);//读取出a
	rewind(pf);//返回原来的位置
	ch = fgetc(pf);
	printf("%c\n", ch);//读取出a

	fclose(pf);
	pf = NULL;

	return 0;
}

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

6. 文件读取结束的判定

6.1 被错误使用的feof

feof:是用于判断文件读取结束的原因

/*
	文本文件读取结束:fgetc:pf==EOF
					  fgets:pf=null
	二进制文件读取结束:fread判断返回值是否小于实际要读的个数
*/
int main()
{
	//EOF
	//feof();//EOF - end of file - 文件结束标志
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
		return 0;
	int ch = fgetc(pf);
	printf("%d\n", ch);//-1

	fclose(pf);
	pf = NULL;

	return 0;
}

文本文件例子

二进制文件例子:

6.2 perror和strerror


/*
	strerror:把错误码对应的错误信息的字符串地址返回
	peerror(s):参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。
*/
int main()
{
	//strerror - 把错误码对应的错误信息的字符串地址返回
	//printf("%s\n", strerror(errno));
	
	//perror
	FILE* pf = fopen("test2.txt", "r");
	if (pf == NULL)
	{
		perror("open file test2.txt");//open file test2.txt:No such file or directory
		return 0;
	}
	//读文件
	
	fclose(pf);
	pf = NULL;

	return 0;
}

C语言 | perror函数使用详解_c语言线程perror_嵌入式大杂烩的博客-CSDN博客

7.练习

 1. 求内存大小

struct {
	int a;//0-3			4字节
	char b;//4			1字节
	short c;//6-7		2字节【因为是2字节,所以要使用2的倍数】
	short d;//8-9		2字节【因为是2字节,所以要使用2的倍数】
};//10字节
//所以我们应该直接+到12字节【地址为12-->(1,2,4)的最大倍数】

2.sizeof(struct)

struct A
{
	int a;//0-3
	short b;//4-5
	//6-7
	int c;//8-11
	char d;//12
	//13 14 15
};//13 -- > 16【(1,2,4)的最大倍数】

struct B
{
	int a;//0-3
	short b;//4-5
	char c;//6
	//7
	int d;//8-11
};//12【(1,2,4)的最大倍数】

int main()
{
	printf("%d\n", sizeof(struct A));//16
	printf("%d\n", sizeof(struct B));//12

	return 0;
}

3.

#pragma pack(4)/*编译选项,表示4字节对齐 平台:VS2013。语言:C语言*/
int main(int argc, char* argv[])
{
	struct tagTest1
	{
		short a;//0-1
		char d;//2
		3
		long b;//4-7
		long c;//8-11
	};//12
	struct tagTest2
	{
		long b;//0-3
		short c;//4-5
		char d;//6
		7
		long a;//8-11
	};//12

	struct tagTest3
	{
		short c;//0-1
		2 3
		long b;//4-7
		char d;//8
		9-11
		long a;//12-15
	};//16
	struct tagTest1 stT1;
	struct tagTest2 stT2;
	struct tagTest3 stT3;

	printf("%d %d %d", sizeof(stT1), sizeof(stT2), sizeof(stT3));
	return 0;
}
#pragma pack()

 

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

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

相关文章

Golang Array 数组使用注意事项和细节

在go数组当中&#xff0c;长度是数据类型的一部分 [3]int *[3]int 数组使用注意事项和细节 1) 数组是多个相同类型数据的组合&#xff0c;一个数组一旦声明/定义了&#xff0c;其长度是固定的&#xff0c;不能动态变化 var a [3]int a[0] 1.1 这样是不行的&#xff0c;必…

“对象创建”模式

通过“对象创建”模式绕开new&#xff0c;来避免对象创建 (new) 过程中所导致的紧耦合(依赖具体类)从而支持对象创建的稳定。它是接口抽象之后的第一步工作。 典型模式 Factory MethodAbstract FactoryPrototypeBuilder Factory Method 动机 (Motivation) 在软件系统中&am…

【数据结构】二叉树的层序遍历(四)

目录 一&#xff0c;层序遍历概念 二&#xff0c;层序遍历的实现 1&#xff0c;层序遍历的实现思路 2&#xff0c;创建队列 Queue.h Queue.c 3&#xff0c;创建二叉树 BTree.h BTree.c 4&#xff0c;层序遍历的实现 一&#xff0c;层序遍历概念 层序遍历&#xff1a;除了先序…

Day981.OAuth 2.0的工作流程与安全问题 -OAuth 2.0

OAuth 2.0的工作流程与安全问题 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于OAuth 2.0的工作流程与安全问题的内容。 一、OAuth 2.0 工作流程串讲 OAuth 2.0 是一种授权协议&#xff0c;这种协议可以让第三方软件代表用户去执行被允许的操作。 那么&#xff0c;…

HI_NAS linux 记录

dev/root 100% 占用解决记录 通过下面的命令查看各文件夹 大小 sudo du --max-depth1 -h # 统计当前文件夹下各个文件夹的大小显示为M 最终发现Var/log 占用很大空间 发现下面两个 log 占用空间很大&#xff0c;直接 rm-rf 即可 HI NAS python3 记录 # 安装pip3 sudo apt u…

4.后端·新建子模块与开发(传统模式)

文章目录 学习资料新建子模块与各层查询entity的列表entitymapper层service层controller层 测试 学习资料 https://www.bilibili.com/video/BV13g411Y7GS?p8&spm_id_frompageDriver&vd_sourceed09a620bf87401694f763818a31c91e b站的学习视频 新建子模块与各层 在r…

Angular变更检测机制

前段时间遇到这样一个 bug&#xff0c;通过一个 click 事件跳转到一个新页面&#xff0c;新页面迟迟不加载&#xff1b; 经过多次测试发现&#xff0c;将鼠标移入某个 tab &#xff0c;页面就加载出来了。 举个例子&#xff0c;页面内容无法加载&#xff0c;但是将鼠标移入下图…

NO.396 旋转数组

题目 给定一个长度为 n 的整数数组 nums 。 假设 arrk 是数组 nums 顺时针旋转 k 个位置后的数组&#xff0c;我们定义 nums 的 旋转函数 F 为&#xff1a; F(k) 0 * arrk[0] 1 * arrk[1] ... (n - 1) * arrk[n - 1] 返回 F(0), F(1), ..., F(n-1)中的最大值 。 生成…

深度学习-卷积神经网络-纹理表示卷积神经网络-卷积神经网络-[北邮鲁鹏]

这里写目录标题 参考文章全连接神经网络全连接神经网络的瓶颈全连接神经网络应用场景 卷积神经网络卷积层(CONV)卷积核卷积操作卷积层设计卷积步长(stride)边界填充特征响应图组尺寸计算 激活层池化层(POOL)池化操作定义池化操作作用池化层超参数常见池化操作 全连接层(FC)样本…

linux相关知识以及有关指令3

在linux的世界中我们首先要有万物皆文件的概念&#xff0c;那么在系统中有那么多的文件&#xff0c;我们该怎么区分呢&#xff1f;文章目录 1. 文件分类2. 文件的权限1). 拥有者和所属组以及other2). 文件的权限3). 粘滞位4). 对于权限修改的拓展知识点a.修改权限b.修改拥有者所…

智慧工地平台源码 劳务实名制、视频监控、扬尘监测、起重机械安全监测

伴随着技术的不断发展&#xff0c;信息化手段、移动技术、智能穿戴及工具在工程施工阶段的应用不断提升&#xff0c;智慧工地概念应运而生&#xff0c;智慧工地平台围绕施工现场管理&#xff0c;构建全方位的智能监控防范体系弥补传统方法和技术在监管中的缺陷&#xff0c;形成…

分享一个Python 写的监控日志log txt文档 的代码

监控log文件的需求 某些特殊原因&#xff0c;想一直看到.log 的最后一行打印&#xff0c;所以写了一些代码监控log &#xff08;有个奇怪需求&#xff0c;就是log 因为重复启动原因&#xff0c;会一直加&#xff0c;不是同一个log&#xff09; 监控界面 涉及的Python代码&…

管理类联考——数学——汇总篇——知识点突破——代数——数列——秒杀

&#x1f41f; ⛲️ 特殊值秒解数列 当数列题目中只有一个条件时&#xff0c;在不违背题意的条件下&#xff0c;可以直接利用特殊值&#xff0c; 令其公差为0或公比为1。 注意&#xff1a;一定要检验是否符合题意&#xff0c;题目中如果出现公差不为0或公比不为1&#xff0c;则…

华为云云耀云服务器L实例评测|部署前后端分离项目

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 学习测评 ✨特色专栏&#xff1a; MyS…

[NLP] LLM---<训练中文LLama2(一)>训练一个中文LLama2的步骤

一 数据集 【Awesome-Chinese-LLM中文数据集】 【awesome-instruction-dataset】【awesome-instruction-datasets】【LLaMA-Efficient-Tuning-数据集】Wiki中文百科&#xff08;25w词条&#xff09;wikipedia-cn-20230720-filteredBaiduBaiKe&#xff08;563w词条&#xff09; …

VIRTIO-SCSI代码分析(3)VIRTIO SCSI数据流处理

VIRTIO SCSI整体数据流如下&#xff1a; IO请求下发过程 虚拟机中通过FIO等下发IO请求&#xff0c;IO请求通过VFS/filesystem&#xff0c;BLOCK层&#xff0c;然后到SCSI层&#xff0c;传递给virtio-scsi驱动&#xff0c;virtio-scsi驱动通过virtioscsi_commit_rqs()下发IO请求…

利用 SOAR 加快事件响应并加强网络安全

随着攻击面的扩大和攻击变得越来越复杂&#xff0c;与网络攻击者的斗争重担落在了安全运营中心 &#xff08;SOC&#xff09; 身上。SOC 可以通过利用安全编排、自动化和响应 &#xff08;SOAR&#xff09; 平台来加强组织的安全态势。这一系列兼容的以安全为中心的软件可加快事…

【100天精通Python】Day63:Python可视化_Matplotlib绘制子图,子图网格布局属性设置等示例+代码

目录 1 基本子图绘制示例 2 子图网格布局 3 调整子图的尺寸 4 多行多列的子图布局 5 子图之间的共享轴 6 绘制多个子图类型 7 实战&#xff1a; 绘制一个大图&#xff0c;里面包含6个不同类别的子图&#xff0c;不均匀布局。 绘制子图&#xff08;subplots&#xff09;…

redis的安装、基础命令学习、常用数据结构

文章目录 前言一、Redis安装1.Ubuntu下安装&#xff08;1&#xff09;切换到root用户下&#xff08;2&#xff09;使用apt安装redis5&#xff08;3&#xff09;为了使redis支持远程连接&#xff0c;修改以下地方&#xff08;4&#xff09;验证安装是否成功 2.Centos7下安装&…

基于Java+SpringBoot+Vue+uniapp点餐小程序(包含协同过滤算法和会员系统,强烈推荐!)

校园点餐小程序 一、前言二、我的优势2.1 自己的网站2.2 自己的小程序&#xff08;小蔡coding&#xff09;2.3 有保障的售后2.4 福利 三、开发环境与技术3.1 MySQL数据库3.2 Vue前端技术3.3 Spring Boot框架3.4 微信小程序 四、功能设计4.1 系统功能结构设计4.2 主要功能描述 五…