【c语言】文件操作,解开你的疑惑

news2024/11/20 10:44:28

文件操作

  • 为什么使用文件
  • 什么是文件
    • 文件的分类
    • 文件名
  • 二进制文件和文本文件
  • 文件的打开与关闭
    • 流与标准流
      • 标准流
    • 文件指针
    • 文件的打开与关闭
  • 文件的顺序读写
  • 文件的随机读写
  • 文件读取结束的判定
  • 文件缓冲区

为什么使用文件

我们程序运行的数据是运行在内存中的,当成程序结束的时候,内存被回收,数据也就销毁了,等再次运行程序的时候,是看不到上次的数据的,所以我们要使用文件将数据保存。

什么是文件

保存在硬盘(磁盘)上的文件就是文件

文件的分类

我们一般把文件分为:

  1. 数据文件
  2. 程序文件

程序文件:源程序文件(后缀为.c),目标文件(windows环境下后缀为.obj),可执行程序(windows环境下后缀为.exe)
数据文件:文件内容不一定是程序,而是程序运行时读取的数据。

在这,我们只讨论数据文件

文件名

文件都有一个唯一的文件标识,以便用户识别和引用。为了方便称呼文件标识又成为文件名
文件名分为以下3个部分:
文件路径,文件名主干,文件后缀
如:c:\csdn\text.txt

  • c:\csdn\是文件路径
  • text是文件名主干
  • .txt是文件后缀

二进制文件和文本文件

根据数据的组织形式,将文件分为二进制文件文本文件
二进制文件:数据在内存中是以二进制的补码的形式存储的,如果我们不加转换的将数据存储到文件中,那这个文件就是二进制文件
文本文件:如果我们将数据转换成ascll码的形式存储到文件中,那这个以ascll码字符形式存储的文件就是文本文件。

一个数在文件中是怎么存储的?

  • 字符一律按照ascll码形式存储
  • 数值型数据可以按照ascll码的形式存储也可以按照二进制的形式存储

举个例子:整数10000,它的二进制是:00000000000000000010011100010000,那么将他以二进制的形式存储时,就如下图,占4字节。
在这里插入图片描述

将10000以ascll码的形式存储:
1的ascll码为:49,转换成二进制就是:00110001
0的ascll码为:48,转换成二进制就是:00110000
共占5个字节
在这里插入图片描述

在这里插入图片描述
测试代码:

int main()
{
    int a = 10000;
    FILE* pf = fopen("text.txt","wb");//以二进制的形式写入数据
    assert(pf);//判断是否打开成功
    fputc(a,pf);
    fclose(pf);//打开文件后要记得关闭文件
    pf = NULL;
    return 0;
}

我们看到文件里面的数据是一个看不懂的符号
在这里插入图片描述
当我们在vs下用二进制编辑器打开这个文本的时候会看到:00000000 10 27 00 00
前面的00000000我们不看,就来看10 27 00 00
将它转换成二进制会得到:0000 0000 0000 0000 0010 0111 0001 0000 对应:0 0 0 0 2 7 1 0,因为在vs下是小端存储,所以我们看到的是10 27 00 00

文件的打开与关闭

流与标准流

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

一般情况下,我们想要向流里写数据或者读取数据都是要打开流后再进行操作。

标准流

我们从键盘输入数据再输出到屏幕上就是打开了标准流。
你可能疑惑:我咋不记得我打开了标准流啊?
那是因为标准流都是默认打开的,在c语言执行的时候默认打开了三个流:

  • stdin,标准输入流
  • stdout,标准输出流
  • stderr,标准错误流

这三个流是默认打开的,所以我们使用printf、scanf函数时能输入输出数据。
stdin、stdout、stderr三个流的类型为:FILE*,文件指针

文件指针

缓冲⽂件系统中,关键的概念是“⽂件类型指针”,简称“⽂件指针”。
每当打开一个文件的时都会在内存中开辟一个文件信息区,用来存放文件的相关信息的(文件名,文件状态,文件的当前位置)
这些信息是保存在⼀个结构体变量中的。该结构体类型是由系统声明的,取名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*pf;

这里定义了一个指向文件信息区的文件指针变量pf,通过这个指针变量可以间接的访问相关文件。
在这里插入图片描述

文件的打开与关闭

在使用的文件时,需要先打开文件,最后再关闭文件。
再编写程序时,打开文件会返回一个FILE*类型文件指针,该指针指向该文件
ANSI C规定,使用fopen函数来打开文件,fclose函数来关闭文件

//打开⽂件
FILE * fopen ( const char * filename, const char * mode );//filename为文件指针,mode为文件的打开方式
 //关闭⽂件 
int fclose ( FILE * stream );
#include<stdio.h>
int main()
{
	FILE*pf=fopen("text.txt","r");
	//....程序
	fclose(pf);
	return 0;
}

文件的打开方式有下面这些:
在这里插入图片描述

文件的顺序读写

顺序读写函数介绍
在这里插入图片描述
上面所讲“适用于所有流指标准流和其他流(如文件流)”。
fgetc函数

int fgetc ( FILE * stream );

字符输入,对于键盘到程序来说,是从键盘输入到程序,对于文件到程序来说,是从程序输入到文件(也可称为读文件)

#include<stdio.h>
int main()
{
	FILE*pf=fopen("text.txt","r");//以读的形式打开文件,如果文件存在,则打开成功,否在打开失败
	if(pf=NULL)//判断文件是否打开成功
	{
	perror("fopen");//打印错误信息
	return 1;//打开失败就提前结束程序
	}
	int ch=0;
	ch=fgetc(pf);//fgetc函数的返回类型为int型
	printf("%c",ch);//输出到屏幕
	fclose(pf);
	pf=NULL;
	return 0;
}

假设这个文件中存放了一个字符a,那么这个字符a将被读取然后赋值到ch中在输出到屏幕上。

fputc函数

int fputc ( int character, FILE * stream );

输出字符,从程序输出到文件中。

int main()
{
	FILE*pf=fopen("text.txt","w");//以写的形式打开文件,如果文件存在,则删除原来的内容后写入数据,如果不存在,则创建新文件
	if(pf=NULL)
	{
		perror("fopen");
		return 1;
	}
	fputc(c,pf);//向文件写入一个字符c
	fclose(pf);
	return 0;
}

对于顺序读写,是根据光标来的
在这里插入图片描述
当写入\读取一个数据后,光标会后移一位,对于读取文件,当读取到文件末尾时,会返回EOF,这表示文件读取结束。
我们可以通过EOF来循环读取文件:

#include<stdio.h>
int main()
{
	FILE*pf=fopen("text.txt","r");//以读的形式打开文件,如果文件存在,则打开成功,否在打开失败
	if(pf=NULL)//判断文件是否打开成功
	{
	perror("fopen");//打印错误信息
	return 1;//打开失败就提前结束程序
	}
	int ch=0;
	while((ch=fgetc(pf))!=EOF)//fgetc函数的返回类型为int型
	{
	printf("%c",ch);//输出到屏幕
	}
	fclose(pf);
	pf=NULL;
	return 0;

剩下的函数读者可自行去了解,用法于上面两个函数相差不大,这边我推荐一个网站来了解学习c语言相关函数
cplusplus

文件的随机读写

函数声明
fseekint fseek ( FILE * stream, long int offset, int origin );
ftelllong int ftell ( FILE * stream );
导管void rewind ( FILE * stream );

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

int fseek ( FILE * stream, long int offset, int origin );
offset为便宜量
origin为文件指针位置

 - SEEK_SET,文件起始位置
 - SEEK_CUR,文件当前位置
 - SEEK_END,文件末尾

int main()
{
    FILE* tmp = fopen("text.txt","r");
    int ch = fgetc(tmp);
    printf("%c\n",ch);
    fseek(tmp,2,SEEK_CUR);
    ch = fgetc(tmp);
    printf("%c\n",ch);
    fseek(tmp,-3,SEEK_END);
    ch = fgetc(tmp);
    printf("%c",ch);
    return 0;
}

假设文件中的内容有:abcdefg,那么读到的内容为“a” “d"以及"b”。

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

 long int ftell ( FILE * stream );
int main()
{
   
    FILE* tmp = fopen("text.txt","r");
    int ch = fgetc(tmp);
    printf("%c\n",ch);
    fseek(tmp,2,SEEK_CUR);
    ch = fgetc(tmp);
    printf("%c\n",ch);
    fseek(tmp,-3,SEEK_END);
    ch = fgetc(tmp);
    printf("%c\n",ch);

    printf("%ld",ftell(tmp));//输出4

    return 0;
}

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

 void rewind ( FILE * stream );

文件读取结束的判定

feof函数
用来判断文件结束的原因是不是因为读取到文件末尾
记住,feof函数不是用来判断文件是否读取结束的

文件缓冲区

ANSIC标准采用“缓冲文件系统”处理数据文件。简单来讲就是:打开文件时内存会开辟一块相应的文件缓冲区,当读取或写入数据时会先将数据放到缓冲区,等缓冲区空间满后在刷新缓冲区将数据读取到程序或者写入到文件中。缓冲区的大小由编译器决定。
在这里插入图片描述
因为有缓冲区的存在,C语⾔在操作⽂件的时候,需要做刷新缓冲区或者在⽂件操作结束的时候关闭⽂件,如果不做,可能导致读写文件失败的问题。(关闭文件时会刷新缓冲区)
在这里插入图片描述

干兴趣的可以通过这段代码观察一下文件 的读写

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

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

相关文章

在线课堂知识付费小程序源码系统 带完整的安装代码包以及搭建教程

系统概述 在线课堂知识付费小程序源码系统是基于当前主流技术栈开发的&#xff0c;支持微信小程序端的在线教育平台解决方案。它不仅包含了课程发布、在线学习、支付系统等基础功能&#xff0c;还融入了社区互动、用户管理、数据分析等高级特性&#xff0c;旨在打造一个全方位…

filezilla-server 1.8.1 设置

filezilla-server 1.8.1 设置&#xff1a; 1. 2. 3. 4. 其他不用配置&#xff0c; 5. 6. 7. 8. 9. 如果外网连不上 filezilla-server 提示无法连接到服务器&#xff0c; 多半是 filezilla-server 所在的电脑没有通过防火墙允许&#xff0c;打开 Windows defender 防…

万兴优转 v15 解锁版安装教程(全能音视频格式转换器)

前言 Wondershare UniConverter&#xff08;万兴优转&#xff09;国产全能音视频格式转换器。万兴格式转换器具有音视频格式转换、合并视频、视频压缩、视频编辑、视频录制、下载视频、元数据修复、VR视频转换、字幕编辑器、GIF制作、DVD刻录等一站式视频工具箱功能。万兴转换…

从文本文件中读取博客数据并将其提取到文件中

通常情况下我们可以使用 Python 中的文件操作来实现这个任务。下面是一个简单的示例&#xff0c;演示了如何从一个文本文件中读取博客数据&#xff0c;并将其提取到另一个文件中。 假设你的博客数据文件&#xff08;例如 blog_data.txt&#xff09;的格式 1、问题背景 我们需…

如何压缩jpg图片到200k以下?跟着我操作!

在现代社交媒体和网络分享的时代&#xff0c;经常需要上传和分享各种图片。然而&#xff0c;有时候大尺寸的JPEG图片可能会成为上传和分享的一道难题&#xff0c;特别是当需要在网络条件不佳或存储空间有限的情况下。为了解决这个问题&#xff0c;我们需要学会如何压缩jpg图片到…

鸿蒙轻内核M核源码分析系列二十 Newlib C

LiteOS-M内核LibC实现有2种&#xff0c;可以根据需求进行二选一&#xff0c;分别是musl libC和newlibc。本文先学习下Newlib C的实现代码。文中所涉及的源码&#xff0c;均可以在开源站点https://gitee.com/openharmony/kernel_liteos_m 获取。 使用Musl C库的时候&#xff0c…

什么是AIGC?AIGC是否会颠覆未来的内容生产模式?普通人如何利用好AI提高内容生产效率?

2024年是AI元年&#xff0c;正好我在AI公司里面工作&#xff0c;对AIGC有着几年的研究&#xff0c;接下来把我这对AIGC的学习经验毫无保留的给大家分享一下 AIGC 的简要介绍 在狭义上&#xff0c;AIGC是指利用AI自动生成内容的生产方式&#xff0c;比如自动写作、自动设计等。…

【机器学习】基于3D CNN通过CT图像分类预测肺炎

1. 引言 1.1. 研究背景 在医学诊断中&#xff0c;医生通过分析CT影像来预测疾病时&#xff0c;面临一些挑战和局限性&#xff1a; 图像信息的广度与复杂性&#xff1a; CT扫描生成的大量图像对医生来说既是信息的宝库也是处理上的负担。每组CT数据可能包含数百张切片&#xf…

金智易表通流程设置的若干问题

1、审批节点的审批人取应用权限组&#xff0c;权限组内任一人审批即可通过 在流程节点的主要配置环节&#xff0c;选择候选组 二、已审菜单要求看到自己审过的也能看到别人审过的&#xff0c;即能看到所有已审的记录 管理设置中取消按钮对流程的依赖&#xff0c;不根据流程审批…

汇编:数组数据传送

要在32位汇编中实现数组数据的传送&#xff0c;可以使用字符串操作指令 MOVS 以及其前缀 REP&#xff0c;可以高效地复制数组数据。 MOVS 指令是一种字符串操作指令&#xff0c;用于将数据从源地址移动到目标地址。MOVS 指令有不同的变种&#xff0c;可以处理不同大小的数据&a…

Mimio安装

mkdir -p /usr/local/develop/minio/bin mkdir -p /usr/local/develop/minio/bin wget https://dl.min.io/server/minio/release/linux-amd64/minio -O /usr/local/develop/minio/bin/minio 编辑脚本 启动脚本 vim /usr/local/develop/minio/start_minio.sh #!/bin/bash # 设…

HTML,CSS,JavaScript实例 —— 齿轮,按钮

文章目录 一、动态按钮二、CSS实例三、滚动的齿轮 一、动态按钮 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style type"text/css">html,body {background: black;height: 100%;displa…

如何在Bing搜索进行广告推广?2024年必应广告投放怎么做?【附开户攻略】

必应&#xff08;Bing&#xff09;作为全球领先的搜索引擎之一&#xff0c;拥有一个独特且庞大的用户群体&#xff0c;尤其在美国和欧洲市场&#xff0c;很多用户选择必应作为他们的主要搜索引擎。通过必应广告&#xff0c;企业可以触达那些在其他搜索引擎上难以接触到的潜在客…

Redis 7.2.x 主从复制+哨兵模式

IP操作系统服务版本192.168.140.153CentOS 7redis-master,sentinel7.2.5192.168.140.156CentOS 7redis-slave,sentinel7.2.5192.168.140.159CentOS 7redis-slave,sentinel7.2.5 一、安装Redis 配置主从复制 参考下面文档&#xff1a; Redis 7.2.x 主从复制-CSDN博客文章浏览…

时间处理基础:Rust 的 chrono 库教程

在开发过程中&#xff0c;我们经常有对时间和日期处理的需求。不论是日历应用、日程安排、还是时间戳记录&#xff0c;准确的时间数据处理都是必不可少的。Rust 社区提供的 chrono 库以其强大的功能和灵活的接口&#xff0c;在 Rust 开发者中广受欢迎。本文将简单介绍 chrono 库…

Nature | 百年未变?博士评定机制该改改了!

19世纪初&#xff0c;德国和法国先后开始授予现代科研博士学位。时至今日&#xff0c;大学的科研与教学早已不同于往昔。但惊人的是&#xff0c;获得和评定博士学位的流程却几乎没变。但改革势在必行。 博士生导师可以从其他教育阶段的创新中学到很多东西。 Innovation in PhD…

成功学为何如此迷人……上瘾……

做自己才是唯一的解药&#xff0c;无需在意他人的看法。 写博客8年与人生第一个502万-CSDN博客 题记&#xff1a;我们并非生来强大&#xff0c;但依然可以不负青春。 原本想好好写一下如何制定一个目标并通过一点一滴的努力去实现&#xff0c;这三年反思发现其实写自己的经历并…

计量校准证书和检定证书区别,企业仪器校准要哪种证书好?

很多企业做校准&#xff0c;会要求校准机构出具相关证书&#xff0c;而有时候也会被机构询问&#xff0c;是要做检定还是校准&#xff0c;出具的证书是要校准证书还是检定证书&#xff1f;那么两者有什么区别呢&#xff1f; 1-检测方式不同 首先两种证书是不同检测方式所给的证…

【Java】解决Java报错:UnsupportedOperationException

文章目录 引言1. 错误详解2. 常见的出错场景2.1 不可修改的集合2.2 抽象类和接口的默认实现2.3 不支持的操作 3. 解决方案3.1 使用支持操作的集合3.2 提供具体实现3.3 检查对象类型和能力 4. 预防措施4.1 使用接口而非实现类4.2 编写防御性代码4.3 使用工厂方法创建集合 5. 示例…

如何快速掌握 Java 枚举类型的定义和使用场景!

Java枚举类型&#xff08;Enum&#xff09;是一种特殊的类&#xff0c;用于表示一组固定的常量。枚举类型在Java 5中引入&#xff0c;通过 enum 关键字来定义。枚举类型不仅可以使代码更具可读性&#xff0c;还能增加类型安全性并减少错误。 一、枚举类型的定义 枚举类型通过…