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

文件简介

文件在程序设计中是一个比较重要的概念,这里所说的文件,是指保存在硬盘、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选项看起来并没有什么作用。和文件操作相关的函数有不少,但多数都很少用到,不值得花费太多时间去学习,读者有了上面学习的基础,也就有了进一步研究其他文件相关函数的能力,在需要的时候可以自行研究。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值