C++ Primer Plus 书之--C++ 文件的基本输入和输出

文件输入和输出

简单的文件I/O

要让程序写入文件, 步骤如下:

1. 创建一个ofstream对象来管理输出流;

2. 将该对象与特定的文件关联起来;

3. 以使用cout的方式使用该对象, 唯一的区别是输出将输出到文件而不是屏幕.

要完成这个功能, 首先应包含头文件fstream, 对于大多数实现来说, 包含该头文件边会自动包含iostream文件. 然后声明一个ofstream对象:

ofstream fout;

接下来, 将这个对象和特定的文件关联起来. 可以使用open()方法. 例如: 要打开文件test.txt:

fout.open("test.txt");

然后, 使用cout的方式使用fout, 例如: 要将Dull Data输出到文件中:

fout << "Dull Data";

以这种方式打开文件来进行输出时, 如果没有这样的文件, 将创建一个新文件, 如果有这样的文件, 则打开文件并清空文件,

 

读取文件的要求与写入文件相似:

1. 创建一个ifstream对象来管理输入流;

2. 将该对象与特定的文件关联起来;

3. 以使用cin的方式使用该对象.

首先, 包含头文件fstream, 声明一个ifstream对象, 将其与文件名关联起来:

ifstream fin;
// 或者可以直接写成一行代码: ifstream fis("test.txt");
fin.open("test.txt");

现在, 可以像使用cin那样使用fin或fis:

char ch;
fin >> ch;
char buf[80];
fin >> buf;
fin.getline(buf, 80);
string line;
getline(fin, line);

注意: 当输入和输出流对象过期(如程序终止)时, 到文件的链接将自动关闭, 另外, 也可以使用close()方法来显示地关闭到文件的链接:

fout.close();
fin.close();

关闭这样的链接并不会删除流, 而只是断开流到文件的链接. 然而,流管理装置仍被保留. 例如, fin对象与它管理的输入缓冲区仍然存在. 可以将流重新链接到同一个文件或另一个文件.

来看一个完整的例子:

// fileio.cpp
#include 
#include 
#include 

int main()
{
	using namespace std;
	string filename;
	
	cout << "Enter name for new file: ";
	cin >> filename;
	
	// fout的参数需要一个c风格的字符串
	ofstream fout(filename.c_str());
	fout << "For your eyes only!\n";
	cout << "Enter your secret number: ";
	float secret;
	cin >> secret;
	fout << "Your secret number is " << secret << endl;
	// 调用close可以刷新文件里的内容
	fout.close();
	
	ifstream fin(filename.c_str());
	cout << "Here are the contents of " << filename << ":\n";
	char ch;
	while(fin.get(ch))
		cout << ch;
	cout << "Done\n";
	fin.close();
	
	return 0;
}

程序运行结果为:

C++ Primer Plus 书之--C++ 文件的基本输入和输出_第1张图片

C++ Primer Plus 书之--C++ 文件的基本输入和输出_第2张图片

 

流状态查看和is_open()

C++文件流类从ios_base类哪里继承了一个流状态成员, 如果一切顺利, 则流状态为0. 其他状态都是通过将特定位设置为1来记录的. 文件流还继承了ios_base类中报告流状态的方法, 因此可以通过检查流状态来判断最后一个流操作是否成功:

fin.open(argv[file]);
if(fin.fail())
{
	...
}

较新的c++实现提供了一种更好的检查文件是否被打开的方法is_open():

if(!fin.is_open())
{
	...
}

打开多个文件.

我们可能需要依次处理一组文件, 例如: 可能要计算某个名称在10个文件中出现的次数, 在这种情况下, 可以打开一个流, 并将它依次关联到各个文件. 这在节省计算机资源方面, 比为每个文件打开一个流的效率高. 使用这种方法, 首先要声明一个ifstream对象(不对它进行初始化), 然后使用open()方法将这个流与文件关联起来:

ifstream fin;
fin.open("test1.txt");
...
fin.close();
fin.clear();
fin.open("test2.txt");
...
fin.close();

命令行处理技术

C++有一种让在命令行环境中运行的程序能够访问命令行参数的机制. 方法是使用下面的main()函数:

int main(int argc, char * argv[])

argc为命令行中的参数个数, 其中包括命令名本身. argv变量为一个指针, 它指向一个指向char的指针. 可以将argv看作一个指针数组, 其中的指针指向命令行参数, argv[0]是一个指针, 指向存储第一个命令行参数的字符串的第一个字符, 以此类推. 假设有下面的命令行:

wc report1 report2 report3

则argc为4, argv[0]为wc, argv[1]为report1, 依次类推. 下面的代码可以把所有命令行参数打印出来:

for(int i = 1; i < argc; i++)
	cout << argv[i] << endl;

上述代码从1开始将只打印命令行参数, 从0开始会打印命令名.

来看一个完整的例子, 将使用命令行技术和文件流技术结合起来:

// count.cpp
#include 
#include 
#include  // for exit()

int main(int argc, char * argv[])
{
	using namespace std;
	if(argc == 1)
	{
		cerr << "Usage: " << argv[0] << " filename[s]\n";
		exit(EXIT_FAILURE);
	}
	
	ifstream fin;
	long count;
	long total = 0;
	char ch;
	for(int file = 1; file < argc; file++)
	{
		fin.open(argv[file]);
		if(!fin.is_open())
		{
			// cerr输出错误信息
			cerr << "Could not open " << argv[file] << endl;
			fin.clear();
			continue;
		}
		count = 0;
		while(fin.get(ch))
			count++;
		cout << count << " characters in " << argv[file] << endl;
		total += count;
		fin.clear();
		fin.close();
	}
	
	cout << total << " characters in all files\n";
	return 0;
}

程序运行结果为:

C++ Primer Plus 书之--C++ 文件的基本输入和输出_第3张图片

C++ Primer Plus 书之--C++ 文件的基本输入和输出_第4张图片

C++ Primer Plus 书之--C++ 文件的基本输入和输出_第5张图片

 

 

 

 

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