C++ 深究fstream打开方式ios::app,ios::ate,ios::in,ios::out

1 学习资料

资料1:C++ 文件和流
资料2:ofstream之ios::ate,ios::app,ios::in,ios::out

2 学习思路

2.1 所需实现功能

实现网页1所说的写入姓名与年龄功能,但是稍作修改,分两次打开文件,第一次写入姓名,第二次写入年龄。

2.2 第一次尝试 默认

#include
#include
using namespace std;
int main()
{
	char data[100];
	
	//第一次打开文件
	ofstream outfile;
	outfile.open("D:\\afile.dat");
	cout << "Writing to the file" << endl;
	cout << "Enter your name:";
	cin.getline(data, 100);
	outfile << data << endl;
	outfile.close();
	
	//第二次打开文件
	ofstream outfile2;
	outfile2.open("D:\\afile.dat");//**待修改语句**
	cout << "Enter your age:";
	cin >> data;
	outfile2 << data << endl;
	outfile2.close();//第二次关闭文件
	
	return 0;
}

输入:
Wu Mingtang
25
输出文件内容为:
C++ 深究fstream打开方式ios::app,ios::ate,ios::in,ios::out_第1张图片
第一次打开文件写入的姓名内容没有了,说明默认方式打开会覆盖原始文件。

2.3 第二次尝试 ios::app

根据资料1所说,使用ios::app模式进行第二次打开,即将待修改语句改为:

	outfile2.open("D:\\afile.dat", ios::app);

运行结果为:
C++ 深究fstream打开方式ios::app,ios::ate,ios::in,ios::out_第2张图片
结果满足预期,说明ofstream对象使用ios::app模式打开文件可以在文件末尾添加新内容。

2.4 第三次尝试 ios::ate

根据资料1所说,ios::ate可以定位到文件末尾,是否可以直接使用该模式打开文件,直接在文件末尾添加新内容?
代码修改为:

	outfile2.open("D:\\afile.dat", ios::ate);

输出文件为:
C++ 深究fstream打开方式ios::app,ios::ate,ios::in,ios::out_第3张图片
说明,以上思路行不通,ios::ate并不能直接在文件尾进行写入操作。

2.5 第四次尝试 ios::ate|ios::in

根据资料2所说,可以使用ios::ate|ios::in模式打开,代码修改为:

	outfile2.open("D:\\afile.dat", ios::ate|ios::in);

输出文件内容为:
C++ 深究fstream打开方式ios::app,ios::ate,ios::in,ios::out_第4张图片
可见ios::ate|ios::in模式与ios::app模式效果一致。

2.6 第五次尝试 0x05

  • 看到操作符“|”就很容易想到这是利用位“或”进行的计算,因此其本质应该是二进制数的“或”操作。
  • 转到ios::in的定义,其源代码为:
	static constexpr _Openmode in = (_Openmode)0x01;
	static constexpr _Openmode out = (_Openmode)0x02;
	static constexpr _Openmode ate = (_Openmode)0x04;
	static constexpr _Openmode app = (_Openmode)0x08;
	static constexpr _Openmode trunc = (_Openmode)0x10;

说明每一种模式是一个由二进制数转化为_Openmode类型的常量

  • _Openmode类型定义为为:
	enum _Openmode
		{	// constants for file opening options
		_Openmask = 0xff};
  • open函数接收的参数就是openmode变量:
	void open(const char *_Filename,
		ios_base::openmode _Mode = ios_base::out,
		int _Prot = (int)ios_base::_Openprot)
  • openmode类型其实就是int型
	typedef int openmode;
  • 归根结底,输出模式其实就是一个int型的变量,只是被各种包装掩盖了其真实面目,因此根据ios::ate|ios::in = 0x05,可以推知将0x05作为open()函数的参数,可以得到同样的结果。
  • 修改代码为:
	outfile2.open("D:\\afile.dat", 0x05);
  • 输出文件为:
    C++ 深究fstream打开方式ios::app,ios::ate,ios::in,ios::out_第5张图片
    可见结果与使用ios::app或者ios::ate|ios::in一致,上面的推论没有问题。

小问题

为什么枚举类型值可以和定义的不一样,基础知识有点不牢固,望各位赐教。

	enum _Openmode
		{	// constants for file opening options
		_Openmask = 0xff};
	static constexpr _Openmode in = (_Openmode)0x01;

你可能感兴趣的:(C++)