C++新经典--文件操作

news2024/9/25 15:27:36

文件简介

文件在程序设计中是一个比较重要的概念,这里所说的文件,是指保存在硬盘、U盘等存储介质上的数据,这些存储介质(简称磁盘)上的数据就是以一个个文件的形式体现,每一个文件有一个对应的名字,称为文件名。操作系统也是以文件为单位对数据进行管理,例如想在磁盘上找数据,需要先按照文件名在该磁盘上找到对应文件,然后把文件中的数据读出来。如果要把数据写到磁盘上,也必须先在磁盘上建立一个文件,然后向这个文件中写入数据。

以往程序执行输出的结果信息都是输出到屏幕上,而在程序执行中输入数据是通过键盘用诸如scanf等函数来输入。随着项目越来越庞大,编写的程序功能越来越复杂,不可避免地会将一些数据放到磁盘上长期存储,以后需要这些数据时再从磁盘上把数据读回到计算机内存中,而针对磁盘数据的存取操作,就要用到磁盘文件功能了。

文件可以看成字符序列,例如,“abcdefg”是一个字符串,也是一个字符序列,它是由一个一个的字符顺序排列组成,把这些数据存储到磁盘上,就形成一个文件。
文本文件或者二进制文件是对于人类来说的,而对于计算机,并不区分是什么类型的文件,保存的都是二进制数据,所以,当用文本形式打开文件时,系统会多做一个工作,就是把二进制数据转换成人类能看懂的ASCII码数据。

现在,再说一说对二进制文件的理解。看如下代码:

    short int a;
    int ilen = sizeof(a);//2
    a=10000;
    printf("断点掐在这里观察\n");

把断点设置在printf所在的行并开始调试跟踪,当断点停到printf行时,用前面章节所讲解的办法查看变量a在内存中的内容,如图12.7所示。

文本文件和二进制文件区别详细解释

根据数据组织形式,把文件分为两种:文本文件(ASCII文件)与二进制文件。
· 文本文件:也称为ASCII文件,文件中的每个字节存放一个ASCII码,代表一个字符,这种文件在打开后能够直接看懂其中的内容。
· 二进制文件:把内存中的数据按照其在内存中的存储形式原样输出到磁盘上存放。这种文件中一般会有很多不可见字符,打开后看到的可能是一堆乱码。

文件的打开

文件在进行读或者写之前,必须要先打开,在读或者写结束之后,必须要关闭,否则会造成资源泄漏或读写失败。文件的打开要调用fopen函数。一般形式如下:

在这里插入图片描述
看如下代码:

FILE* fp;
fp = fopen("Al","r");	//打开名字叫"A1"的文件,""表示文件使用方式为只读

这里注意到,fopen函数返回一个指向A1文件的指针,这个指针被赋值给了fp。这样,就可以认为fp指向了A1文件。
FILE结构体:每次用fopen函数打开一个文件,系统都会开辟出一块内存,这块内存大小是sizeof(FILE),这块内存用来存放和文件相关的信息,诸如文件名、文件使用方式、当前文件位置等。

通过调用fopen函数,可以告诉系统三个信息:

1)需要打开的文件名。
2)文件使用方式,如是读还是写,“r”表示读,后面会讲到。
3)让哪个指针变量指向被打开的文件,这里是fp指针变量。

文件使用方式(只包含一部分)如表12.1所示。
在这里插入图片描述
表12.1中的内容不必死记硬背,需要时查阅即可。但这里可以记几个比较常用的,如r、w、a。当然,也有一些规律可循:
(1)有w表示往文件中写入。
(2)有r表示从文件中读出。
(3)有b表示二进制文件。
(4)有a表示追加内容到文件末尾。
(5)有“+”表示既能从文件中读出,又能往文件中写入。

此外,还需要知道的是,每个打开的文件都有一个当前位置指针,其实就是保存在FILE结构里的一个char*型的字符指针(不同版本编译器可能细节不同,但道理都相同)。这个位置指针的用途就是代表当前从文件的哪个位置开始读/写数据,对于读来讲,每读出1字节数据,这个位置指针会自动往后移动1字节,以指向下一字节,这样,下次再读时自然就从下一字节开始。

当用fopen函数打开文件时,有可能打开失败,例如文件不存在时一定会打开失败,此时fopen函数就会返回一个空(NULL)。看如下代码:

在这里插入图片描述

文件的关闭

文件只有在成功用fopen函数打开之后,才存在文件关闭的问题,否则,不存在关闭的问题。在用fopen函数打开文件成功后,一般都会对文件进行读写操作,读写完毕之后,应该关闭这个文件。为什么要关闭这个文件呢?有两个原因:(1)释放这个文件占用的内存资源,如果资源使用后却不释放,那么,当资源耗尽就会导致程序运行崩溃,所以必须养成资源用完后及时释放的好习惯。
(2)往文件中写数据时不会立即往磁盘上写,系统会把数据写到一个叫“缓冲区”的地方,缓冲区满时系统才往磁盘文件上写,写完之后把缓冲区清空继续等待用户往文件中写数据。试想,当把数据往文件中写时,假如缓冲区此时没满,那么在没有关闭文件的情况下退出了程序的运行(或者突然停电导致计算机关机),那么缓冲区中的数据就没来得及写到磁盘文件上,造成数据丢失。关闭文件这个动作会触发系统把缓冲区中的数据立即写到磁盘上,这就避免了缓冲区中的数据丢失问题。

所以,打开的文件在不使用时及时关闭,非常有必要。文件的关闭要调用fclose函数,一般形式如下:
在这里插入图片描述

if(fp != NULL)
	fclose(fp);	//fp就是fopen函数的返回值(文件指针)

文件关闭后,fp就不能再被使用(读/写文件),否则程序会报异常。fclose()函数有返回值,一般0表示关闭成功,非0表示关闭失败,但该返回值用处不大(例如如果文件关闭失败,再关闭一次应该也还会失败),所以一般不用去理会这个返回值。

文件的读写

文件读写有许多相关的函数,这里介绍几个常用的。
(1)fputc函数:用于把一个字符写到磁盘文件。调用形式看如下代码——将字符ch输出到fp所指向的文件中:
在这里插入图片描述
如果fputc执行成功,返回值就是输出字符的ASCII码值;如果执行失败,返回EOF。EOF是EndOfFile(文件末尾)的缩写,是系统提供的一个宏定义,代表-1。如下:
在这里插入图片描述
看看如下范例:

FILE *fp;		//FILE是一个结构,fp是指向结构FILE的指针变量(文件指针)
fp = fopen("FTest.txt","w");	//为写而打开文件
if (fp == NULL)
{
	printf("文件打开失败\n");
}
else
{
	//文件打开成功才走这里
	char reco = fputc('a',fp);
	if (reco == EOF)	//注意fputc失败时,会返回EoF
	{
		
		//写失败时的处理代码
	}
	else
	{
		reco = fputc('d',fp);	//这里并没有判断是否写成功,不建议这样写,不安全
		reco = fputc('e',fp);	//这里依旧没有判断是否写成功
		fclose(fp);	//文件打开成功的情况下,应该及时关闭文件
    }
}

在上面的范例中有几点说明:
· 当执行到fopen这行代码时,文件写入方式指定为w,表示为写而打开一个文本文件FTest.txt,FTest.txt刚开始是不存在的,因此,如果fopen执行成功,则系统会创建该文件,如果该文件存在,则fopen执行成功时该文件中原始的内容会被覆盖。

· 调用fopen函数时可以指定所要打开的文件路径,但范例中并没有指定路径,系统可能会到当前项目所在的目录(通过Visual Studio来运行时)或该可执行程序目录(双击直接运行可执行程序)寻找FTest.txt文件并尝试打开,如果该文件并不存在,系统会在当前项目所在的目录或该可执行程序所在的目录下创建FTest.txt文件。

(2)fgetc函数:用于从指定文件读入一个字符。调用形式看如下代码——从fp所指向的文件中读入一个字符到reco中:

char reco = fgetc(fp);

如果fgetc执行成功,则返回读入的字符;如果执行失败或者整个文件读到末尾,则返回EOF。看看如下范例:

    FILE *fp;    //FILE是一个结构,fp是指向结构FILE的指针变量(文件指针)
    fp = fopen("FTest.txt","r");     //文件刚打开,文件当前位置指针指向开头
    if (fp == NULL)
    {
        printf("文件打开失败");
    }
    else
    {
        //文件打开成功才走这里
        char reco = fgetc(fp);
        //每读一个字符,文件当前位置指针自动向下走一个字符
        while (reco != EOF){    //读入失败或者到文件结束这个条件都成立
            putchar(reco);  //在屏幕上输出一个字符
            reco = fgetc(fp); //再次读一个字符
        }

        fclose(fp);
    }

上面的范例有个弊端,该范例中是用EOF(-1)来判断读入的内容是否到达文件结束。但一旦该文件中真存在一个值为-1的字符(该字符的十六进制是FF,用fgetc读入进来就是-1),那么,用EOF这种判断方式来判断是否读到文件结束,就会出现错误,所以需要换一种范例写法,引入feof函数。

(3)feof函数:用来判断文件是否结束(文件当前位置指针是否指向文件末尾)。调用形式看如下代码:

feof(fp);

如果文件结束,则返回1;如果文件没结束,则返回0。不管使用fopen函数时是以什么样的文件使用方式打开文件(例如用r还是用rb都没关系),feof函数都能够正确地判断文件是否结束。改造一下上面的范例代码,只需要修改范例中的while语句所在行,其他代码行不需要做任何修改。把while语句行修改为如下即可:

while(!feof(fp))	//文件没有结束    

上面的范例中,利用fopen函数打开文件时,如果在“文件使用方式”参数中增加b选项(打开一个二进制文件),代码如下:

 fp = fopen("FTest.txt","rb");

执行程序后会发现,整个程序的运行结果并没有发生什么改变,也就是说,是否增加b选项看起来并没有什么作用。和文件操作相关的函数有不少,但多数都很少用到,不值得花费太多时间去学习,读者有了上面学习的基础,也就有了进一步研究其他文件相关函数的能力,在需要的时候可以自行研究。

文件读写实战操练

这里将展示一个有实用价值的功能:游戏在线升级功能中的配置文件读取功能。这种读取功能适合于读取各种配置文件,请读者举一反三,达到最好的学习效果。网络游戏中经常用到游戏在线升级功能,该功能的工作原理是:从网络上下载一个游戏最新的配置文件到本地(配置文件一般都是文本文件),读取这个文件,然后跟原来的本地配置文件内容比较,通过发现的差异来决定是否进行游戏的在线升级功能。

如下就是一个配置文件:

在这里插入图片描述
该配置文件一共有7行,其中第2行是一个版本信息描述,正是通过这个信息的比较,确定是否进行游戏的在线升级。要进行这样的演示:假定该配置文件已经下载到当前文件夹下,现在需要把这个文件一行一行读出来,显示在屏幕上。因为该文件的每一行就是一条相对完整的信息,看看如何利用文件相关的函数来读取该文件。当前,配置文件内容已经保存到config.txt文件中,以二进制的方式在Visual Studio中打开config.txt并进行观察,如图12.12所示。

未完。。。

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

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

相关文章

Kotlin开发笔记:使用委托进行拓展

Kotlin开发笔记:使用委托进行拓展 导言 在OO语言(面向对象)中,我们经常会用到委托或者代理的思想。委托和代理在乍一看很相似,其实其各有各的侧重点,这里我引用ChatGpt的回答: 委托(Delegation&#xff09…

内涝防控一张图!解锁内涝防控全周期解决方案

随着暴雨高发季的到来,如何提升城市内涝治理水平,构筑人民生活美好空间成为各地关注的重点。近日, 住房和城乡建设部、应急管理部印发《关于加强城市排水防涝应急管理工作的通知》,明确提出,各地要加强城市内涝整治和排…

java Spring Boot properties多环境配置拆分文件管理

上文 java Spring Boot yml多环境拆分文件管理优化 我们用yml 做了一个多环境配置文件的拆分管理 我们将 application.yml 改为 application.properties 参考代码如下 spring.profiles.activedev我们知道 yml 是用 : 来区分高低基本 而 properties是直接通过 . 来表达 其他基本…

解锁暑假云端生活:铁威马NAS助你打造个性化体验

暑假转眼过半,大家一定度过一段非常美好的时光吧。朋友圈被去各地旅游的、看各种演唱会的、各种各样的观影读后感刷屏...生活很精彩,但如何高效地管理、享受和分享自己的文件、照片和影音内容成为困扰我们的难题。在这方面,铁威马NAS成为了越…

Unity自定义脚本的 初始模版

参考博主:Unity修改创建的脚本模板,Unity脚本模板路径_unity hub 怎么改脚本模板_先生沉默先的博客-CSDN博客 【100个 Unity实用技能】 ☀️ | Unity自定义脚本的初始模版_unity 模板脚本_呆呆敲代码的小Y的博客-CSDN博客 一,将脚本放到Ed…

【uniapp】使用permission获取录音权限及实现录音功能

需求 app获取录音权限权限, 实现录音并且播放功能 实现 一. 使用permission获取录音权限 原博 : https://www.wanjunshijie.com/note/uniapp/3203.html 1.1 manifest.json 配置权限 android.permission.RECORD_AUDIO 1.2 permision使用和下载 ( 自行百度搜索即可 ) 1.3 获…

【探索Linux】—— 强大的命令行工具 P.4(编译器 gcc/g++ 使用)

阅读导航 前言一、编译的四大过程(背景知识)1. 预处理(Preprocessing)2. 编译(Compilation)3. 汇编(Assembly)4. 链接(Linking) 二、gcc的使用1. 概念2. gcc主…

Docker 容器内无法使用vim命令 解决方法

目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 进入Docker容器后 无法使用vim编辑器,出现如下问题:bash: vim: command not found 如图所示: 想着通过apt-get 安装vim,出现如下问题: root@b9f0fd330d5b:/# apt-get install vim Reading package lists... Done B…

VR全景加盟项目如何开展?如何共赢VR时代红利?

VR全景作为一个新兴蓝海项目,相信有着很多人刚接触VR行业的时候都会有这样的疑问:VR全景加盟后项目如何开展?今天,我们就从项目运营的三个阶段为大家讲解。 一、了解项目时 目前VR全景已经被应用到各行各业中去,学校、…

通过postgresql的Ltree字段类型实现目录结构的基本操作

通过postgresql的Ltree字段类型实现目录结构的基本操作 将这种具有目录结构的excel表存储到数据库中,可以采用树型结构存储 DROP TABLE IF EXISTS "public"."directory_tree"; CREATE TABLE "public"."directory_tree" (…

使用 PyTorch 进行高效图像分割:第 1 部分

一、说明 在这个由 4 部分组成的系列中,我们将使用 PyTorch 中的深度学习技术从头开始逐步实现图像分割。我们将在本文中从图像分割所需的基本概念和想法开始本系列。 图1:宠物图像及其分割掩码(来源:牛津-IIIT宠物数据集) 图像分…

OpenLayers入门,OpenLayers加载船讯网航海地图

专栏目录: OpenLayers入门教程汇总目录 前言 本章实现OpenLayers加载船讯网航海地图。 二、依赖和使用 "ol": "^6.15.1"使用npm安装依赖npm install ol@6.15.1使用Yarn安装依赖yarn add olvue中如何使用: vue项目使用请参考这篇文章:

Maven之JDK编译问题

IDEA Maven 默认使用 JDK 1.5 编译问题 IDEA 在「调用」maven 时,IDEA 默认都会采用 JDK 1.5 编译,不管你安装的 JDK 版本是 JDK 7 还是 JDK 8 或者更高。这样一来非常不方便,尤其是时不时使用 JDK 7/8 的新特性时。如果使用新特性&#xff…

[10min速通]STM32CubemMX配置W25Q128

[10min速通]🦏STM32CubemMX配置W25Q128 文章目录 [10min速通]🦏STM32CubemMX配置W25Q1281、下载源码2、配置Cube2.1 基础配置2.2 SPI配置 3、配置MDK3.1 添加源文件3.2 管理源文件3.3 完成接口配置 4、接口介绍4.1 初始化4.2 擦除4.3 写入4.4 读取 5、代…

AntDB数据库受邀参加【ACDU 中国行】,共促行业发展和创新

作为数据的集中存储和管理系统,数据库在现代信息化时代扮演着至关重要的角色,随着人工智能,物联网和大数据时代的到来,数据库的发展需要进一步拓展其广度和深度,持续创新,实现技术进步,以更好地…

香港服务器备案会通过吗?

​  对于企业或个人来说,合规备案是网络运营的基本要求,也是保护自身权益的重要举措。以下内容围绕备案展开话题,希望为您解开疑惑。 香港服务器备案会通过吗? 目前,香港服务器无法备案,这是由于国内管理规定的限制…

Salient主题 - 创意多用途和WooCommerce商城主题

Salient主题是下一代WordPress主题,给任何人带来专业的设计结果,而不需要任何编码。Salient 提供永久更新的专业剖面模板库,目前有超过425个可供选择 – 所有这些都充满热情并坚持高标准的审美质量。 网址: Salient主题 - 创意多用途和WooCo…

Linux下安装nodejs

1、下载nodejs 点击前往:Download | Node.js 2、解压 tar -xvf node-v18.16.0-linux-x64.tar.xz mv node-v18.16.0-linux-x64/ /usr/local/nodejs 3、 建立软链接 此时的bin文件夹中已经存在node以及npm,如果你进入到对应文件的中执行命令行一点问题…

vue3 路由缓存问题

目录 解决问题的思路: 解决问题的方案: 1、给roter-view添加key(破坏复用机制,强制销毁重建) 2、使用beforeRouteUpdate导航钩子 3、使用watch监听路由 vue3路由缓存:当用户从/users/johnny导航到/use…

估算森林蓄积量哨兵2号变量计算详情

哨兵2号估算森林蓄积量变量计算详细步骤 变量概括哨兵2号变量计算详情1. 生物物理变量计算2. 植被指数3. 纹理特征 变量概括 需要计算的变量参数有: 生物物理变量 采用SNAP软件的工具生成5个生物物理变量。植被指数 采用gdal库计算,共17个植被指数变量…