C++对数据文件的操作

文件的概述

文件是程序设计中一个重要的概念。所谓“文件”,一般是指相关数据的集合。计算机中的一批数据是以文件的形式存放在外部介质(如磁盘、光盘和U盘)上的。操作系统是以文件为单位对数据进行管理的,也就是说,如果想找存在外部介质上的数据,必须先按文件名找到所指定的文件,然后再从该文件中读取数据。要向外部介质上存储数据也必须先建立一个文件(以文件名标识),才能向它输出数据。

文件的分类

外部文件和内部文件

(1)外部文件:指磁盘文件、光盘文件和U盘文件。目前使用最广泛的是磁盘文件,在程序中对光盘文件和U盘文件的使用方法与磁盘文件相同。之后所说的文件都是指磁盘文件。
(2)内部文件:指在程序中运行的文件,更正式的称谓是“文件流对象”。对用户来说,常用到的文件有两大类,一类是程序文件(program file),如C++的源程序文件(.cpp)、目标文件(.obj)、可执行文件(.exe)等;一类是数据文件(data file),在程序运行时,常常需要将一些数据(运行的最终结果或中间数据)输出到磁盘上存放起来,以后需要时再从磁盘中输入到计算机内存。这种磁盘文件就是数据文件。程序中的输入和输出的对象就是数据文件。

文本文件和二进制文件

根据文件中数据的组织形式,可分为ASCII文件和二进制文件。
(1)ASCII文件:ASCII文件又称文本(text)文件或字符文件,它的每1字节放一个ASCII代码,代表一个字符。
(2)二进制文件:又称内部格式文件或字节文件,是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放。

对于字符信息,在内存中是以ASCII代码形式存放的,因此,无论用ASCII文件输出还是用二进制文件输出,其数据形式是一样的。但是对于数值数据,二者是不同的。例如有一个长整数100000,在内存中占4字节,如果按内部格式直接输出,在磁盘文件中占4字节,如果将它转换为ASCII码形式输出,则要占6字节。

文件流类和文件流对象

文件流是以外部文件为输入输出对象的数据流。输出文件流是从内存流向外部文件的数据,输入文件流是从外部文件流向内存的数据。每一个文件流都有一个内存缓冲区与之对应。

注意:文件流与文件的概念,不要误以为文件流是由若干文件组成的流。文件流本身不是文件,而只是以文件为输入输出对象的流。若要对磁盘文件输入输出,就必须通过文件流来实现。

到目前为止,用户使用的iostream标准库提供了cin和cout方法分别用于从标准输入读取流和向标准输出写入流。而cin、cout就是流对象,C++是通过流对象进行输入输出的。由于cin、cout已在iostream中事先定义,所以用户不需自己定义。

在C++的I/O类库中不仅可以看到除了标准输入输出流类istream、ostream和iostream类外,还有3个专门用于文件操作的文件类。
(1)ifstream类,它是从istream类派生的,用来支持从磁盘文件的输入。
(2)ofstream类,它是从ostream类派生的,用来支持向磁盘文件的输出。
(3)fstream类,它是从iostream类派生的,用来支持对磁盘文件的输入输出。
在这里插入图片描述
对磁盘文件的操作是通过文件流对象(而不是cin和cout)实现的。文件流对象是用文件流类定义的,而不是用istream和ostream类来定义的。

注意:要在C++中进行文件处理,必须在C++源代码文件中包含头文件< iostream >和< fstream >。

打开文件

打开文件是指在文件读写之前做必要的准备工作,包括:为文件流对象和指定的磁盘文件建立关联,以便使文件流流向指定的磁盘文件。然后指定文件的工作方式,如该文件是作为输入文件还是输出文件,是ASCII文件还是二进制文件等

1. 调用文件流的成员函数open(磁盘文件名,输入输出方式)

  • 第1个参数表示要打开文件的文件名。磁盘文件名可以包括路径。
    注意:如缺省路径,则默认为当前目录下的文件。

  • 第2个参数指定文件的打开方式。
    输入文件流的默认值ios::in,意思是按输入文件方式打开文件;输出文件流的默认值ios::out,意思是按输出文件方式打开文件;对于输入输出文件流没有默认值的打开方式,在打开文件时,应指明打开文件的方式。此时myFile.txt是一个输出文件,接收从内存输出的数据。

2. 在定义文件流对象时指定参数

在声明文件流类时定义了带参数的构造函数,其中包含了打开磁盘文件的功能。因此,可以在定义文件流对象时指定参数,调用文件流类的构造函数来实现打开文件的功能。

ifstream、ofstream、fstream 3个文件流类的构造函数所带的参数与各自的成员函数open()所带的参数完全相同。因此,在说明这3种文件流类的对象时,通过调用各自的构造函数也能打开文件。

ofstream outfile("file.txt", ios::out);

注意:一般多用此形式,比较方便。作用与open()函数相同。

下面是open()函数的标准语法。open()函数是fstream、ifstream和ofstream对象的一个成员
在这里插入图片描述
在这里插入图片描述
说明:

  • (1)新版本的I/O类库中不提供ios::nocreate和ios::noreplace。

  • (2)每一个打开的文件都有一个文件指针,该指针的初始位置由I/O方式指定,每次读写都从文件指针的当前位置开始。每读入1字节,指针就后移1字节。当文件指针移到最后,就会遇到文件结束符EOF(文件结束符也占1字节,其值为-1),此时流对象的成员函数eof()的值为非0值(一般设为1),表示文件结束了。

  • (3)可以用“位或”运算符“|”对输入输出方式进行组合
    在这里插入图片描述
    在这里插入图片描述

  • (4)如果打开操作失败,open()函数的返回值为0(假),如果是用调用构造函数的方式打开文件的,则流对象的值为0。可以据此测试打开是否成功。例如:

if(outfile.open("D:\\myFile.txt", ios::app) == 0)
		cout << "open error"; 

if(!outfile.open("D:\\myFile.txt", ios::app))
		cout << "open error"; 

关闭文件

当C++程序终止时,它会自动关闭刷新所有流,释放所有分配的内存,并关闭所有打开的文件。但程序员应该养成一个好习惯,在程序终止前关闭所有打开的文件。关闭文件用成员函数close()。

outfile.close();

所谓关闭,实际上是解除该磁盘文件与文件流的关联,原来设置的工作方式也会失效,这样,就不能再通过文件流对该文件进行输入或输出。此时可以将文件流与其他磁盘文件建立关联,通过文件流对新的文件进行输入或输出。

综合样例:

#include<iostream>
#include<fstream>
using namespace std;

int main()
{
	ofstream outfile;							//定义输出文件流对象 
	outfile.open("D:\\myFile2.txt", ios::out);	//使文件流与myFile.txt文件建立关联 
	
	if(outfile.is_open())
	{
		cout << "文件打开成功!" << endl;
	}
	outfile.close();
	return 0;
}

运行结果如下:
在这里插入图片描述
【程序分析】本例演示了一个数据文件的打开与关闭操作。首先使用ofstream类定义一个对象outfile,用于对磁盘文件的输出操作。然后通过输出文件流对象outfile打开指定磁盘文件,在文件流对象和磁盘文件之间建立联系。接着通过if语句进行判断。最后关闭文件。

文件的读写

如果文件的每1字节中均以ASCII代码形式存放数据,即1字节存放一个字符,这个文件就是ASCII文件(或称文本文件)。程序可以从文本文件中读入若干字符,也可以向它输出一些字符。

文本文件的读写

文本文件读写在文件缓冲区中进行,文件的读写操作可以用以下两种方法:

方法一:用流插入运算符“<<”和流提取运算符“>>”输入输出标准类型的数据。

“<<”和“>>”都已在iostream中被重载为能用于ostream和istream类对象的标准类型的输入输出。由于ifstream和ofstream分别是ostream和istream类的派生类,因此它们从ostream和istream类继承了公有的重载函数,所以在对磁盘文件的操作中,可以通过文件流对象和流插入运算符“<<”及流提取运算符“>>”实现对磁盘文件的读写,如同用cin、cout和<<、>>对标准设备进行读写一样。

编写程序,向一个文件中写入10个整数。

#include<iostream>
#include<fstream>
using namespace std;

int main()
{
	int a[10];
	char f[50];
	cout << "请输入文件名:" << endl;
	cin >> f;
	ofstream outfile(f, ios::out);
	if(!outfile)
	{
		cerr << "文件无法打开!" << endl;
		exit(1); 
	}
	cout << "请输入10个整数:" << endl;
	for(int i = 0; i < 10; i++)
	{
		cin >> a[i];
		outfile << a[i] << " ";		//向磁盘文件输出数据 
	}
	outfile.close();
	return 0;
}

【程序分析】对程序说明如下:
(1)程序中用#include命令包含了头文件fstream,这是由于在程序中用到文件流类ofstream,而ofstream是在头文件fstream中定义的。注意:在使用一些老编译器时,程序中用到cout,但没有包含iostream头文件,这是因为在头文件fstream中包含了头文件iostream,所以编译器可以正常编译。但是在Visual Studio 2017中不允许这样操作。
(2)参数ios::out可以省略。如果不写此项,则默认为ios::out。
一下两种写法等价:

ofstream outfile(f, ios::out);

ofstream outfile(f);

(3)系统函数exit()用来结束程序运行。exit()的参数为任意整数,可用0,1或其他整数。由于用了exit()函数,某些老版本的C++要求包含头文件stdlib.h,而在新版本的C++则不要求包含。
(4)在程序中用“cin>>”从键盘逐个读入10个整数,每读入一个就将该数向磁盘文件输出,输出的语句为:

outfile << a[i] << " ";

可以看出,用法和向显示器输出是相似的,只是把标准输出流对象cout换成文件输出流对象outfile而已。由于是向磁盘文件输出,所以在屏幕上看不到输出结果。

编写程序,从一个文件中读出内容。

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int a[10], i;
	char f[100];
	cout << "请输入文件名:" << endl;
	cin >> f;			//以读的模式打开文件 
	ifstream infile(f, ios::in);
	if(!infile)
	{
		cerr << "open error!" << endl;
		exit(1); 
	}
	cout << "读出文件中的内容:" << endl;
	for(i = 0; i < 10; i++)
	{
		infile >> a[i];		//从磁盘文件读入10个整数,顺序放在a数组中 
		cout << a[i] << " ";
	}
	cout << endl;
	infile.close();
	return 0;
}

运行结果如下:
在这里插入图片描述
【程序分析】本例是以读的模式打开一个文件。在代码中首先定义int型的数组a和变量i,再定义一个字符型数组f。数组a用于存放文件中的内容,数组f用于输入文件名。如果该文件不存在,则打开失败。所以我们输入的是事先存在了的数据文件outFile,就是前一个例子里创建的

方法二:用文件流的put()、get()、getline()等成员函数进行字符的输入输出。

例:创建一个输出文件流,并输出一串字符

#include<iostream>
#include<fstream>
using namespace std;

int main()
{
	ofstream outFile("D:\\outFile.txt", ios::out);	//声明文件流对象 
	if(!outFile)	//使用错误流对象输出错误信息 
		cerr << "Open file or create file error." << endl;
	else			//输出数据到与对象outFile关联的文件中 
		outFile << "This is a test file";
}

或者

#include<iostream>
#include<fstream>
using namespace std;

int main()
{
	ofstream outFile;	//声明文件流对象 
	outFile.open("D:\\outFile.txt", ios::out); 
	if(!outFile)	//使用错误流对象输出错误信息 
		cerr << "Open file or create file error." << endl;
	else			//输出数据到与对象outFile关联的文件中 
	{
		outFile << "This is a test file";
		outFile.close();
	}
		
	outFile.close();
}

例:使用插入与提取运算符对磁盘文件进行读写

#include<fstream>
#include<iostream>
using namespace std;

int main()
{
	ofstream outfile1("myfile1.txt");		//写数据 
	outfile1 << "Hello!...China Cyprus" << endl;
	outfile1.close();
	
	outfile1.open("myfile1.txt", ios::app);	//追加数据 
	int x = 1212, y = 6868;
	outfile1 << x << " " << y << endl;
	outfile1.close(); 
	
	char str1[80], str2[80];
	int x2, y2;
	ifstream infile1("myfile1.txt");
	infile1 >> str1 >> str2;
	infile1 >> x2 >> y2;
	infile1.close();
	cout << "str1 = " << str1 << endl;
	cout << "str2 = " << str2 << endl;
	cout << "x2 = " << x2 << endl;
	cout << "y2 = " << y2 << endl;
	return 0;
}

运行结果如下:
在这里插入图片描述

如果喜欢我的文章,请记得三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持,下期更精彩!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值