关键词不能为空

当前您在: 主页 > 英语 >

文件输入输出流

作者:高考题库网
来源:https://www.bjmy2z.cn/gaokao
2021-03-03 12:57
tags:

-

2021年3月3日发(作者:拮据)



C++


中的文件输入


/


输出



收藏




简介



本教 程将以


C++


最基本的文件


I/O


(输出


/


输出)开始。此后,我将从更深入 的方面,为你展


示一些技巧,并分析给出一些有用的函数。


< /p>


你需要对


C++


有一个较好的理解,否则 这个教程于你而言将是陌生而毫无用处。





你的第一个程序





首先我将给出一段代码,


接着再逐行进行解释。


我们的第一个程序将建立一个文件,


并写入


一些字符:





#include




void main() //


程序从这里开始运行



{


ofstream SaveFile(“cpp


-home< /p>


.txt”);



SaveFile << “Hello World, from


-


and Loobian!”;



();


}


仅仅如此吗?没错!


这个程序将在当前运行目录下建立一个名为



的文件,


并向


它写入“


Hello World, from and Loobian!







下面给出各行的含义:





#include



——



你需要包含此文件以使用


C++


的文件输入< /p>


/


输出函数。注意:一旦


包含了这个文件 ,你不再需要(为了使用


cout/cin


)包含


iostream.h


,因为


fstream.h< /p>


已经自


动包含了它。


< br>在这个头文件中声明了若干个类,包括


ifstream



ofstream



fstream


,它们都继承自


istream



ostream


类。





ofstream SaveFile(“cpp


-


”);



1



ofstream


即“


output file stream


(输出文 件流)



。它将建立一个句柄(


han dle



,以便我们


以后能以一个文件 流的形式写入文件。



2


< p>
SaveFile


——



这是文件句柄的名字,当然,你还可以换用任何一个你想要的名称。


< br>3



(





);


——



打开名为



的文件。如果程序运行的当前目录已经


存在这样一个文件,< /p>


则它将被替换掉;万一不存在,程序也会为你创建一个为文件,你不必

为此而担心。



现在,让我们稍微深入一点点。首先,我要 指出的是:


ofstream


是一个类。因此

< br>ofstream


SaveFile(





);


这一语句将创建一个 该类的对象;而我们在括号中所传递的参数


实际上将传给构造函数:

在这里我们将我们要建立的文件的名称作为实际参数传递给了该类


的构造函数。当然 ,我们还可以传递其它的一些信息,不过我以后再对其进行讲解。





SaveFile <<



Hello World, from and Loob ian!



;


——



<<


”看起来是不

< p>
是很亲切?不错,想必你已经在


cout <<


中见到过。这是一个预定义好的运算符。不管怎么




说,这行语句所做的,是将上面的那段文本写入文件。正如前 面所提到的,


SaveFile


是一个


文件句柄,它关联一个打开的流式文件。所以,我们只须输入句柄名,再跟着输入“


<<




然后接着写下一串用引号括起来的 文本,


就可以实现对文件的写入。


如果我们想写入的是某


个变量的值而不是带引号的文本,也只须像通常使用


cout <<


一样将变量传递给句柄对象,


像这样:



SaveFile << variablename;


就可以了!





();


——



既然我们打开了一个流文件,那么当我们用完它之后,就必须关闭它。

< br>SaveFile



ofstream

< br>类的一个对象,而该类


(ofstream)


有一个用于 关闭文件的成员函数,即


close()


函数。因此,我们只 要依次输入文件句柄名,点号和


close()


,就可以关闭该 文件!



注意:一旦你关闭文件,在你重新打开它以前,就再不 能对它进行访问。





以上就是一个可以写文件的最简单程序。


的确很容易!


不过,


正如你即将在以后部分的教程


中所看到的,还有更多的 东西要学呢!



读取文件





你已经看到了应该如何写文件。现 在,当我们已经得到



文件时,我们将要读取

它,并且将内容打印在屏幕上。



首先,

< br>我要指出的是,有很多种方法可以读取文件。以后我会向你们介绍所有的方法(就我


所知的)


。此刻,我先向你展示最佳的方法(我认为的)


。< /p>



正如你已经熟悉的——我将首先给出一段程序代码,然后,我会 详细地对它进行解释说明:





#include




void main() //


程序从这里开始



{






ifstream OpenFile(








char ch;






while(!())






{









(ch);









cout << ch;






}






();


}




你想 必已经了解首行的意义所在,而剩下的部分将由我为你解释。



ifstream OpenFile(




)


——



我猜它对现在的你而言多少会熟 悉些!


ifstream



示“


input file stream(


输入文件流

< br>)



。在前一节的程序中,出现的则是

< br>ofstream


,它的意义是



output


file


stream(

< br>输出文件流


)



。前一节的程序 是进行文件的写操作,这就是它用



output(

< p>
输出


)



来表示的原因。


而本节的程序则是读取一个文件,


这就是它用

< br>“


input(


输入


)



来表示的原因。这一行剩下的代码于你而言应当是熟悉的了:


OpenFile



ifstream


类的一个




对象,它 将关联一个输入文件流;而用引号括住的内容,就是将要打开的文件的名称。



请注意:这里没有对要打开的文件是否存在进行测试!以后我将向你指出如何进行检测。





char


ch;


——



声明一个字符数组(


array


of


type


char



。只是有一点要提醒你:这样的数组



arrays< /p>


)只能存储一个


ASCII


字符。





while(!())


——



如果已经到达文件末尾,


eof(


)


函数将返回一个非零值。因此我


们所设计的这个循环将一直持续 ,


直至我们的文件操作到达文件末尾。


这样我们就可以遍历


整个文件,以便对它进行读取。





(ch);


——



OpenFile


是类


ifstream


的一个对象。该类声明了一个 名为


get(


)


的成


员函数。只要我们拥有该对象,我们自然就可以调用这个函数。


get(


)


函数从相应的流文件


中读出一个字符,并 将其返回给变量。在本例中,


get(


)

函数只带一个参数——用于存储所


读取的字符的变量。所以,调用

< br>(ch)


后程序将会从


OpenFile


流中读取一个字符


并存入变量


ch

中。



注意:


如果你再次调用该函 数,


它将读取下一个字符,而不是原来的那一个!你过后将理解


为什么会这样。



这就是我们要不断反复循环直至读操作到达文 件尾的原因。


每循环一次,


我们将读出一个字

< br>符并将它保存在


ch


中。





cout << ch;


——



显示


c h


变量值,它保存了读取得到的字符。





();


——



我们打开了一个流式文件,


就需要关闭它。


使用


close()


函数即可将它关闭,


这和前一节的一样!


< /p>


注意:一旦你关闭了一个文件,在你重新打开它之前,你不能再对它进行访问。

< p>




大功告成了!我希 望你能明白我的解释。当你编译并运行这个程序的时候,它应当会输出:




Hello World, from -


and Loobian!”





掌握输入


/


输出流





在这一章里,


我会提及一些有用的函数。


我将为你演示如何打开 一个可以同时进行读、


写操


作的文件;此外,我还将为你介绍其 它打开文件的方法,以及如何判断打开操作是否成功。


因此,请接着往下读!

< p>


到目前为止,


我已为你所展示的只是单一的打开 文件的途径:


要么为读取而打开,


要么为写

入而打开。但文件还可以以其它方式打开。迄今,你应当已经认识了下面的方法:





ifstream OpenFile(“cpp


-


”);





噢,这可不是唯一的方法!正如以 前所提到的,以上的代码创建一个类


ifstream


的对象, 并


将文件的名字传递给它的构造函数。


但实际上,


还存在有不少的重载的构造函数,


它们可以


接受不止 一个的参数。同时,还有一个


open()


函数可以做同样的事 情。下面是一个以上代码


的示例,但它使用了


open()


函数:







ifstream OpenFile;


(“cpp


-


” );





你 会问:它们之间有什么区别吗?哦,我曾做了不少测试,结论是没有区别!只不过如果你


要创建一个文件句柄但不想立刻给它指定一个文件名,


那么你可以使用

< br>open()


函数过后进行


指定。顺便再给出一个要使用


open()


函数的例子:如果你打开一个文件,然后关闭了它 ,又


打算用同一个文件句柄打开另一个文件,这样一来,你将需要使用

< br>open()


函数。



考虑以下的代码示例:





#include




void read(ifstream &T) //pass the file stream to the function


{





//the method to read a file, that I showed you before






char ch;








while(!())






{









(ch);









cout << ch;






}











cout << endl <<


}




void main()


{






ifstream T(






read(T);






();








(






read(T);






();


}




据此,只要





并存储了文本内容,你将看到这些内容。


现在,


该向你演示的是,


文件名 并不是你唯一可以向


open()


函数或者构造函数

< p>
(其实都一样)


传递的参数。下面是一个函数原型:





ifstream OpenFile(char *filename, int open_mode);




你应当知道


filename


表示文件的名称(一个字符串)


,而新出现 的则是


open_mode


(打开模




式)



op en_mode


的值用来定义以怎样的方式打开文件。下面是打开模式的列表:



名称



描述




ios::in


打开一个可读取文件




ios::out


打开一个可写入文件




ios::app


你写入的所有数据将被追加到文件的末尾, 此方式使用


ios::out



ios::ate


你写入的所有数据将被追加到文件的末尾, 此方式不使用


ios::out



ios::trunk


删除文件原来已存在的内容(清空文件)




ios::nocreate


如果 要打开的文件并不存在,那么以此参数调用


open()


函数将 无法进行。




ios::noreplace


如果要打开的文件已存在,试 图用


open()


函数打开时将返回一个错误。




ios::binary


以二进制的形式打开一个文件。







实际上 ,以上的值都属于一个枚举类型的


int


常量。但为了让你的编 程生涯不至于太痛苦,


你可以像上表所见的那样使用那些名称。



下面是一个关于如何使用打开模式的例子:





#include




void main()


{






ofstream SaveFile(








SaveFile <<








();


}




正如你在表中所看到的:


使用


ios::ate


将会从文件的末尾开始执 行写入。


如果我没有使用它,


原来的文件内容将会被重新写入的 内容覆盖掉。


不过既然我已经使用了它,


那么我只会在原


文件的末尾进行添加。所以,如果



原有的内容 是这样:



Hi! This is test from !


那么执行上面的代码后,程序将会为它添上“


That



s new!



,因 此它看起来将变成这样:



Hi! This is test from -


!That’s n


ew!

假如你打算设置不止一个的打开模式标志,只须使用


OR


操 作符或者是



|


,像这样:





ios::ate | ios::binary




我希望现在你已经明白“打开模式”是什么意思了!



现在,


是时候向你展示一些真正有用的东西了!


我敢打赌你现在还不知道应当怎样打开一个


可以同时进行读取和写入操作的文件!下面就 是实现的方法:





fstream File(“cpp


-


”,ios::in | ios::out);





实际上,


这只是一个声明语句。


我将在下面数行 之后给你一个代码示例。


但此时我首先想提




及一些你应当知道的内容。



上面的代码创建了一个名为“


File


”的流 式文件的句柄。如你所知,它是


fstream


类的一个


对象。


当使用


fstream


时,你应当指定


ios::in


ios::out


作为文件的打开模式。


这样,

< p>
你就可


以同时对文件进行读、写,而无须创建新的文件句柄。噢,当然,你 也可以只进行读或者写


的操作。那样的话,相应地你应当只使用


ios::in


或者只使用


ios::out


——



要思考的问题是:


如果你打算这么做,为什么你不分别用


ifstream


ofstream


来实现呢?



下面就先给出示例代码:





#include




void main()


{






fstream File(








File <<


将“


Hi!


”写入文件











static char str[10]; //


当使用


static


时,数组会自动被初始化


















//


即是被清空为零










(ios::beg); //


回到文件首部





















//


此函数将在后面解释







File >> str;






cout << str << endl;








();


}




OK


,这儿又有一些新东西,所以我将逐行进行解释:





fstream File(





, ios::in | ios::out);


——



此行创建一个


fstream


对象,执行时将会 以读


/


写方式打开


文件。这意味着你可以同时读取文件并写入数据。





File <<



Hi!



;


——



我打赌你已经知道它的意思了。





static char str[10];


——



这将创建一个容量为

< p>
10


的字符数组。我猜


static


对你而言或者有些


陌生,如果这样就忽略它。这只不过会在创建数组的同时对 其进行初始化。





(ios::beg);


——



OK


,我要让你明白它究竟会做些什么,因此我将以一些有点儿离< /p>


题、但挺重要的内容开始我的解释。



还记得它么:





while(!())






{











(ch);









cout << ch;






}




你是 不是曾经很想知道那背后真正执行了什么操作?不管是或不是,


我都将为你解释。


这是


一个


while


型循环,它会一直反复,直至程序的操作到达文件的尾端。但这个循环如何知道






< p>
















,< /p>









< p>






inside-pointer


< br>”的东西,它表明你读取(写入也一样)已经到了文件的哪个位置,就像


记事本中 的光标。而每当你调用


(ch)


的时候,它会返回当前位置的字 符,存储



ch


变量中,并将这一内置 指针向前移动一个字符。因此下次该函数再被调用时,它将会


返回下一个字符。而这一过 程将不断反复,直到读取到达文件尾。


所以,让我们回到那行代


码:函数


seekg()


将把内置指针定位到指定的位置(依你 决定)


。你可以使用:





ios::beg


——



可将它移动到文件首端



ios::end


——



可将它移动到文件末端





或者,


你可以设定向前或向后跳转的 字符数。


例如,


如果你要向定位到当前位置的

< br>5


个字符


以前,你应当写:



(-5);


如果你想向后跳过


40< /p>


个字符,则应当写:



(40);


同时,我必须指出,函数


seekg()


是 被重载的,它也可以带两个参数。另一个版本是这样子


的:



(-5,ios::end);


在这个例子中,你将能够读到 文件文本的最后


4


个字符,因为:


< /p>


1


)你先到达了末尾(


ios::end




2


)你接 着到达了末尾的前五个字符的位置(


-5



为什么你会读到


4


个字符而不是


5


个?噢,只须把最后一个看成是“丢掉了”

< br>,因为文件最


末端的“东西”既不是字符也不是空白符,那只是一个位置(译注: 或许


ios::end


所“指”


的根本 已经超出了文件本身的范围,


确切的说它是指向文件最后一个字符的下一个位置,



点类似


STL


中的 各个容器的


end


迭代点是指向最后一个元素的下一位置。这样 设计可能是


便于在循环中实现遍历)




你现在可能想知道为什么我要使用到这个函数。呃,当我把“


H i


”写进文件之后,内置指针


将被设为指向其后面??也就是文 件的末尾。


因此我必须将内置指针设回文件起始处。


这就


是这个函数在此处的确切用途。



File >> str;


——



这也是新鲜的玩意儿!噢,我确信这行代码让你想起了


cin >> .


实际上,它


们之间有着相当的关联。此行会从文件中读 取一个单词,然后将它存入指定的数组变量中。



例如,如果文件中有这样的文本片断:



Hi! Do you know me?


使用


File


>>


str


,则只会将“


Hi!


” 输出到


str


数组中。你应当已经注意到了,它实际上是将


空格作为单词的分隔符进行读取的。



由于 我存入文件中的只是单独一个“


Hi!



,我不需要写一个


while


循环,那会花费更多的时


间来写代码。这就是我使用此方法的原因。顺便说一下,


到目前为止,


我所使用的读取文件



while


循环中,程序读文件的方式是一个字符一个字符进行读取的。然而你也可以一个单

< p>



词一个单词地进行读取,像这样:





char str[30]; //


每个单词的长度不能超过


30


个字符



while(!())






{









OpenFile >> str;









cout << str;






}




你也可以一行一行地进行读取,像这样:





char line[100]; //


每个整行将会陆续被存储在这里



while(!())


{


e(line,100); // 100


是数组的大小



cout << line << endl;


}




你现在可能想知道应当使用哪种方法。


嗯,

我建议你使用逐行读取的方式,


或者是最初我提


及的逐字符 读取的方式。


而逐词读取的方式并非一个好的方案,


因为它不会 读出新起一行这


样的信息,


所以如果你的文件中新起一行时,< /p>


它将不会将那些内容新起一行进行显示,


而是

加在已经打印的文本后面


(


即是不换行

)


。而使用


getline()


或 者


get()


都将会向你展现出文件的


本来面目!



现在,


我将向你介绍如何 检测文件打开操作是否成功。实现上,好的方法少之又少,我将都


会涉及它们。需要注意 的是,出现“


X


”的时候,它实际可以以“

o






i


”来代替,或者


也可以什么都不是 (那将是一个


fstream


对象)





1


:最通 常的作法





Xfstr


eam File(“cpp


-


”);



if (!File)


{


cout << “Error opening the file! Aborting…



n”;



exit(1);


}







2


:如果文件已经被创建,返回一个错误





ofstream File(




if(!File)


{


cout << “Error opening the file! Aborting…



n”;



exit(1);




}




例< /p>


3


:使用


fail()

< br>函数





ofstream File(




if(())


{



cout << “Error opening the file! Aborting…



n”;



exit(1);


}





3


中的新 出现的东西,



fail()


函数。如 果有任何输入


/


输出错误


(不是在文件 末尾)


发生,


它将返回非零值。



我也要讲一些我认为非常重要的内容!


例如,


如果你已经创建一个流文件对象,


但你没有进


行打开文件操作 ,像这样:





ifstream File; //


也可以是一个


ofstream




这样,


我们就拥有一个文件句柄,但 我们仍然没有打开文件。


如果你打算迟些打开它,


那么


可以用


open()


函数来实现,我已经在本教 程中将它介绍了。但如果在你的程序的某处,你可


能需要知道当前的句柄是否关联了一个 已经打开的文件,那么你可以用


is_open()


来进行检< /p>


测。如果文件没有打开,它将返回


0 (false)


;如果文件已经打开,它将返回


1 (true)


。例如:





ofstream File1;


(


cout << _open() << endl;




上面的代码将会返回


1


(译注:指


_open()


函数,下句同)


,因为我们已经打开了一个


文件(在第二行)


。而下面的代码则会返回


0


,这是由于 我们没有打开文件,而只是创建了


一个流文件句柄:



ofstream File1;


cout << _open() << endl;





检测输入


/


输出的状态标志





在此我不打算解释“标志(


flags



”一词的含义,不过假如你真的完全不理解关于这方面的


概念,


那么将本章读过一遍之后也许你对此会得到一些认识,


我也相信你同样能理解 这部分


的理论。


尽管如此,


如果你还是 不明白标志在


C++


中的含义,


我推荐 你阅读一些关于这个主


题的资料。



好,让我们开始吧。



C++


中负责的输入


/


输出的系统包括了关于每一个输 入


/


输出操作的结果的记录信息。这些当


前的状态信息被包含在


io_state


类型的对象中。


io_state


是一个枚举类型(就像


o pen_mode


一样)


,以下便是它包含的值(译注:表中第 一列为枚举值的名称,第二列为该值相应含义


-


-


-


-


-


-


-


-



本文更新与2021-03-03 12:57,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/700112.html

文件输入输出流的相关文章