【图书推荐】《Linux C与C++一线开发实践(第2版)》_linux c与c++一线开发实践pdf-CSDN博客
《Linux C与C++一线开发实践(第2版)(Linux技术丛书)》(朱文伟,李建英)【摘要 书评 试读】- 京东图书
LinuxC\C++编程技术_夏天又到了的博客-CSDN博客
4.9.1 流的概念
在C++语言中,数据的输入和输出包括对标准输入设备(键盘)和标准输出设备(显示器)、外存磁盘上的文件以及内存中指定的字符串存储空间(当然可用该空间存储任何信息)进行输入输出。对标准输入设备和标准输出设备的输入输出简称为标准I/O,对外存磁盘上的文件的输入输出简称为文件I/O,对内存中指定的字符串存储空间的输入输出简称为(字符)串I/O。
“流”就是“流动”,是物质从一处向另一处流动的过程。C++流是指信息从外部输入设备(如键盘和磁盘)向计算机内部(即内存)输入和从内存向外部输出设备(如显示器和磁盘)输出的过程,这种输入输出过程被形象地比喻为“流”。为了实现信息的内外流动,C++系统定义了I/O类库,其中的每一个类都称作相应的流或流类,用以完成某一方面的功能。一个流类定义的对象也时常被称为流。例如根据文件流类fstream定义的一个对象fio可称作fio流或fio文件流,用它可以同磁盘上的一个文件相联系,实现对该文件的输入和输出,fio就等同于与之相联系的文件。
因为C++兼容C,所以C中的输入输出函数依然可以在C++中使用,但是很显然,直接把C的那套输入输出搬到C++中肯定无法满足C++的需求,更重要的一点是,C中的输入输出有类型要求,只支持基本类型,因此C++设计了易于使用的并且多种输入输出流接口统一的I/O类库,并且支持多种格式化操作,还可以自定义格式化操作。总体来说,C++中有3种输入输出流。
(1)标准I/O流:内存与标准输入输出设备之间信息的传递。
(2)文件I/O流:内存与外部文件之间信息的传递。
(3)字符串I/O流:内存变量与表示字符串流的字符数组之间信息的传递。
C++引入I/O流,将这3种输入输出流接口统一起来,使用符号“>>”读取数据的时候,不用去管是从何处读取数据,使用符号“<<”写数据的时候,也不需要管是写到哪里去。
4.9.2 流的类库
C++语言系统为实现数据的输入和输出定义了一个庞大的类库,其中ios为根基类,其余都是它的直接或间接派生类,它直接派生4个类:输入流类istream、输出流类ostream、文件流基类fstreambase和字符串流基类strstreambase。C++系统中的I/O类库的所有类被包含在iostream、fstream和strstream这3个系统头文件中。我们可以用图4-4来表示各个类的继承关系。
图4-4
头文件<fstream>提供了3个文件流类:ifstream、ofstream和fstream。
值得注意的是,要在C++中进行文件处理,必须在C++源码文件中包含头文件<fstream>。此外,在C++新标准中,头文件都把.h去掉了,如#include<fstream.h>现在要用:
#include<fstream>
using namespace std;
同时要把标准命名空间加上。但是fstream.h和fstream并不是完全等价的。在旧头文件里的fstream.h,如果使用ifstream file的默认参数声明一个输入文件流,当这个要读的file文件不存在时,会自动创建一个空文件,从而给判断文件是否存在造成了很多麻烦。如果使用新标准fstream,就不会创建空文件,从而可以用while(!file)来判断文件是否存在,通过返回数值来指导程序运行。
类似地,头文件ostream.h与iostream也是不同的。iostream.h在旧的C++标准中使用,新标准中用iostream,还要引用命名空间std。iostream.h慢慢地不再使用了,比如微软的VC6可以使用iostream.h,VS 2008已经不能使用iostream.h了。好像不习惯将没有.h 结尾的文件称为头文件,但与时俱进吧,头文件不一定要.h。
4.9.3 打开文件
在从文件读取信息或者向文件写入信息之前,必须先打开文件。ofstream和fstream对象都可以用来打开文件进行写操作,如果只需要打开文件进行读操作,就使用ifstream对象。被打开的文件在程序中由一个流对象来表示(这些类的一个实例),而对这个流对象所做的任何输入输出操作实际上就是对该文件所做的操作。要通过一个流对象打开一个文件,需要使用它的成员函数open()。open()函数是fstream、ifstream和ofstream对象的一个成员,该函数声明如下:
void open(const char *filename, ios::openmode mode);
其中,第一参数指定要打开的文件的名称和位置,第二个参数定义文件被打开的模式。文件打开模式如表4-3所示。
可以把以上两种或两种以上的模式结合使用。例如,如果想要以写入模式打开文件,并希望截断文件,以防止文件已存在,那么可以使用下面的代码:
ofstream outfile;
outfile.open("file.dat", ios::out | ios::trunc );
类似地,如果想要打开一个文件用于读写,可以使用下面的代码:
fstream afile;
afile.open("file.dat", ios::out | ios::in );
又比如,如果想要以二进制方式打开文件example.bin来写入一些数据,可以这样写:
ofstream file;
file.open ("example.bin", ios::out | ios::app | ios::binary);
ofstream、ifstream和fstream类的成员函数open都包含一个默认打开文件的方式,这3个类的默认方式各不相同,如表4-4所示。
只有在函数被调用且没有声明方式参数的情况下,默认值才会被采用。如果函数被调用时声明了任何参数,默认值将被完全改写,而不会与调用参数组合。
由于对类ofstream、ifstream和fstream的对象所进行的第一个操作通常都是打开文件,因此这些类都有一个构造函数可以直接调用open函数,并拥有同样的参数。这样,我们就可以通过以下方式进行与上面同样的定义对象和打开文件的操作:
ofstream file ("example.bin", ios::out | ios::app | ios::binary); // 定义对象的同时直接打开文件
两种打开文件的方式都是正确的。
另外,我们可以通过调用成员函数is_open(),来检查一个文件是否已经被顺利地打开了:
bool is_open();
该函数返回一个布尔值,值为真(true)代表文件已经被顺利打开,值为假(false)则相反。
4.9.4 关闭文件
当文件读写操作完成之后,我们必须将文件关闭以使文件重新变为可访问的。关闭文件需要调用成员函数close(),它负责将缓存中的数据释放出来并关闭文件。close()函数是fstream、ifstream和ofstream对象的一个成员函数,声明如下:
void close();
这个函数一旦被调用,原先的流对象就可以被用来打开其他的文件了,这个文件也就可以重新被其他的进程访问了。为防止流对象被销毁时还联系着打开的文件,析构函数将会自动调用关闭函数close()。
4.9.5 写入文件
在C++编程中,我们使用流插入运算符(<<)向文件写入数据,就像使用该运算符输出信息到屏幕上一样。唯一不同的是,在这里使用的是ofstream或fstream对象,而不是cout对象。
4.9.6 读取文件
在C++编程中,我们使用流提取运算符(>>)从文件读取信息,就像使用该运算符从键盘输入信息一样。唯一不同的是,在这里使用的是ifstream或fstream对象,而不是cin对象。
下面来看一个例子,以读写模式打开一个文件。在向文件afile.dat写入用户输入的信息之后,程序从文件读取信息,并将其输出到屏幕上。
【例4.13】用C++流的方式读写文件
(1)打开Visual Studio Code,新建文本文件test.cpp,输入代码如下:
#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
char data[100];
// 以写模式打开文件
ofstream outfile;
outfile.open("afile.dat");
cout << "Writing to the file" << endl;
cout << "Enter your name: ";
cin.getline(data, 100);
// 向文件写入用户输入的数据
outfile << data << endl;
cout << "Enter your age: ";
cin >> data;
cin.ignore();
// 再次向文件写入用户输入的数据
outfile << data << endl;
// 关闭打开的文件
outfile.close();
// 以读模式打开文件
ifstream infile;
infile.open("afile.dat");
cout << "Reading from the file" << endl;
infile >> data;
// 在屏幕上写入数据
cout << data << endl;
// 再次从文件读取数据,并显示它
infile >> data;
cout << data << endl;
// 关闭打开的文件
infile.close();
return 0;
}
(2)上传test.cpp到Linux,在终端下输入命令g++ -o test test.cpp,然后运行test,结果如下:
# g++ -o test test.cpp
# ./test
Writing to the file
Enter your name: zww
Enter your age: 61
Reading from the file
zww
61
可以看到在同目录下生成了一个文件afile.dat,查看里面的内容可得:
# cat afile.dat
zww
61
上面的例子中使用了cin对象的附加函数,比如getline()函数从外部读取一行,ignore()函数会忽略掉之前读语句留下的多余字符。