zl程序教程

您现在的位置是:首页 >  其他

当前栏目

c++IO库之文件输入输出详细整理,建议赶紧收藏!!!

2023-03-14 22:51:58 时间

c++IO库之文件输入输出


引言

  • 头文件fstream定义了三个类型来支持文件IO: ifstream从一个给定文件读取数据,ofstream向一个给定文件写入数据,以及fstream可以读写给定文件。
  • 这些类型提供的操作与我们之前使用过的对象cin和cout的操作一样。特别是,我们可以用IO运算符(<<和>>)来读写文件,可以用getline从一个ifstream读取数据。
  • 除了继承自iostream类型的行为之外,fstream中定义的类型还增加了一些新的成员还管理与流相关的文件。除了这些操作,我们可以对fstream,ifstream和ofstream对象调用这些操作,但不能对其他IO类型调用这些操作。

fstream的特有的操作

fstream fstrm

创建一个未绑定的文件流。fstream是头文件中定义的一个类型

fstream fstrm(s)

创建一个fstream,并打开名为s的文件。s可以是string类型,或者是一个指向C风格字符串的指针。这些构造函数是explicit的。默认的文件模式mode依赖于fstream的类型

fstream fstrm(s,mode)

与前一个构造函数相似,但按指定mode打开文件

fstrm.open(s)

打开名为s的文件,并将文件与fstrm绑定。s可以是一个string或一个指向C风格字符串指针。默认的文件mode依赖于fstream的类型。返回void.

fstrm.close()

关闭与fstrm绑定的文件,返回void

fstrm.is_open()

返回一个bool值,指出与fstrm关联的文件是否成功打开且尚未关闭


使用文件流读对象

  • 当我们想要读写一个文件时,可以定义一个文件流对象,并将对象与文件关联起来。
  • 每个文件流都定义了一个名为open的成员函数,它完成一些系统相关的操作,来定位给定的文件,并视情况打开为读或写模式。
  • 创建文件流对象时,我们可以提供文件名(可选的)。如果提供了一个文件名,则open会自动被调用:
	ifstream in(ifile);//构造一个ifstream并打开给定文件
	ofstream out;//输出文件流未关联到任何文件
  • 定义一个输入流in,它被初始化为从文件中读取数据,文件名由string类型的参数iflie指定。
  • 输出流out未与任何文件关联。
  • 在新c++标准中,文件名既可以是string类型,也可以是C风格字符串指针。
  • 旧版本的标准库只可以使用C风格字符串数组。

用fstream代替iostream&

  • 再要求使用基类型对象的地方,我们可以用继承类型的对象来替代。这意味着,接受一个iostream类型引用(或指针)参数的函数,可以用一个对象的fstream(或sstream)类型来调用。
  • 也就是说,当有一个函数接受一个ostream&参数,我们可以传给它一个ofstream对象,对istream&和ifstream同理.
  • 下面举一个例子:
#include<iostream>
using namespace std;
#include<fstream>	
class Book
{
public:
	Book():sellSum(0),isbn(0),price(0){}
	int isbn;//书本的编号
	int price;//书本的价格
	int sellSum;//该书的销售总额
};
//输入卖出书本的编号,价格
istream& read(istream& is, Book& item)
{
	int sumValue = 0;
	//从文件中读取信息存入item中
	is >> item.isbn >> item.price;
	return is;
}
//输出卖出书本的编号,价格和销售总额
ostream& print(ostream& os, Book& item)
{
	//输出信息并写入当前文件中
	cout<<"当前书本的编号为: " << item.isbn << "  价格: " << item.price << "  销售总额: " << item.sellSum << endl;
	os << "当前书本的编号为: " << item.isbn << "  价格: " << item.price << "  销售总额: " << item.sellSum << endl;
	return os;
}
int main(int argc, char** argv)
{
	ifstream input("read.txt");//打开销售记录文件
	if (!input.is_open())
		cerr << "文件打开失败" << endl;
	ofstream output("print.txt");//打开输出文件
	if (!output.is_open())
		cerr << "文件打开失败" << endl;
	Book total;//保存销售总额变量
		while (read(input,total))//读取销售记录
		{
			total.sellSum += total.price;
			print(output, total) << endl;
		}
	return 0;
}

重要的部分是对read和print的调用,虽然两个函数定义时指定的形参分别是istream&和ostream&,但我们可以向他们传递fstream对象


成员函数open和close

  • 如果我们定义了一个空文件流对象,可以随后调用open来将它与文件关联其起来:
	ifstream in(ifile);//构筑一个ifstrean并打开给定文件
	ofstream out;//输出文件流未与任何文件关联
	out.open(ifile + ".copy");//打开指定文件
  • 如果调用open失败,failbit会被置位.failbit用来指出一个IO操作失败了因为调用open可能失败,进行open是否成功的检测是一个好习惯:
if(out)//检查open是否成功,如果open成功,我们就可以使用文件了
  • 一旦一个文件流已经打开,它就保持与对应文件的关联.实际上,对一个已经打开的文件流调用open会失败,并会导致failbit被置位. 随后的试图使用文件流的操作都会失败。
  • 为了将文件流关联到另外一个文件,必须首先关闭已经关联的文件。一旦文件成功关闭,我们可以打开新的文件。
in.close();//关闭文件
in.open(ifile+"2");//打开另外一个文件

自动构造和析构

#include<iostream>
using namespace std;
#include<fstream>	
#include<vector>
#include<string>
istream& read(istream& is, string& item)
{
	int sumValue = 0;
	is >> item;
	return is;
}
void print(string& item)
{
	//输出信息
	cout<<item << " ";
}
int main(int argc, char** argv)
{
	vector<string> s = { "1.txt","2.txt","3.txt","4.txt","5.txt" };
	string item;
	for (int i = 0; i < s.size(); ++i)
	{
		ifstream input(s[i]);
		read(input, item);
		print(item);
	}

	return 0;
}
  • 每个循环构造一个新的名为input的ifstream对象,并打开它来读取给定的文件。
  • 因为input是while循环的局部变量,它在每个循环步中都要创建和销毁一次
  • 当一个ifstream离开其作用域时,与之关联的文件会自动关闭。
  • 在下一步循环中,input会再次被创建
  • 当一个fstream对象被销毁时,close会被自动调用

文件模式

  • 每个流都有一个关联的文件模式,用来指出如何使用文件。
  • 下表列出了文件模式和它们的含义:

in

以读的方式打开

out

以写的方式打开

app

每次写操作前均定位到文件末尾

ate

打开文件后立即定位到文件末尾

trunc

截断文件

binary

以二进制方式进行IO

无论哪种方式打开文件,我们都可以指定文件模式,调用open打开文件时可以,用一个文件名初始化流来隐式打开文件可以。指定文件模式有如下限制:

  • 只可以对ofstream或fstream对象设定out模式
  • 只可以对ifstream或fstream对象设定In模式
  • 只有当out也被设定时才可以设定trunc模式
  • 只要trunc没被设定,就可以设定app模式,在app模式下,即使没有显示指定out模式,文件也总是以输出方式被打开
  • 默认情况下,即使我们没有指定trunc,以out模式打开的文件也会被截断。为了保留以out模式打开的文件的内容,我们必须同时指定app模式,这样只会将数据追加写到文件末尾;或者同时指定in模式,即打开文件同时进行读写操作.
  • ate和binary模式可以用于任何类型的文件流对象,且可以与其他任何文件模式组合使用。

每个文件流类型都定义了一个默认的文件模式,当我们未指定文件模式的时候,就使用默认模式。 与ifstream关联的文件默认以in模式打开; 与ofstream关联的文件默认以out模式打开; 与fstream关联的文件默认以in和out模式打开。 、


以out模式打开文件会丢失已有数据

默认情况下,当我们打开一个ofstream时,文件的内容会被丢弃。阻止一个ofstream清空给定文件内容的方法是同时指定app模式:

//在这几条语句中,file1都被截断
ofstream out("file1");//隐含的以输出模式打开文件并截断文件
ofstream ou2("file1",ofstream::out);//隐含的截断文件
ofstream out3("file1",ofstream::out|ofstream::trunc);
//为了保留文件内容,我们必须显示指定app模式
ofstream app("file2",ofstream::app);//隐含为输出模式
ofstream app2("file2",ofstream::out|ofstream::app);

保留被ofstream打开的文件中已有的数据的唯一方法是显示指定dpp或者in模式.


每次调用open时都会确定文件模式

对于一个给定流,每当打开文件时,都可以改变其文件模式:

ofstream out;//未指定文件打开模式
out.open("scratchpad");//模式隐含设置为输出和截断
out.close();//关闭out,以便我们将其用于其他文件
out.open("a",ofstream::app);//模式为输出和追加
out.close();

通常情况下,out模式意味着同时使用trunc模式,使用trunc模式打开一个已经写了数据的文件,文件里面的内容会被全部清空 每次打开文件时,都要设置文件模式,可能是显示设置,也可能是隐式地设置。当程序未指定模式前,就使用默认值