C++文件的输入输出讲解非常清晰.docx
- 文档编号:7140731
- 上传时间:2023-01-21
- 格式:DOCX
- 页数:24
- 大小:30.13KB
C++文件的输入输出讲解非常清晰.docx
《C++文件的输入输出讲解非常清晰.docx》由会员分享,可在线阅读,更多相关《C++文件的输入输出讲解非常清晰.docx(24页珍藏版)》请在冰豆网上搜索。
C++文件的输入输出讲解非常清晰
C++中的文件输入/输出
(1)
原作:
IliaYordanov, loobiancpp-home.
简介
本教程将以C++最基本的文件I/O(输出/输出)开始。
此后,我将从更深入的方面,为你展示一些技巧,并分析给出一些有用的函数。
你需要对C++有一个较好的理解,否则这个教程于你而言将是陌生而毫无用处。
你的第一个程序
首先我将给出一段代码,接着再逐行进行解释。
我们的第一个程序将建立一个文件,并写入一些字符:
#include
voidmain()//程序从这里开始运行
{
ofstreamSaveFile(“cpp-home.txt”);
SaveFile<<“HelloWorld,from.cpp-home.andLoobian!
”;
SaveFile.close();
}
仅仅如此吗?
没错!
这个程序将在当前运行目录下建立一个名为cpp-home.txt的文件,并向它写入“HelloWorld,from.cpp-home.andLoobian!
”。
下面给出各行的含义:
#include
注意:
一旦包含了这个文件,你不再需要(为了使用cout/cin)包含iostream.h,因为fstream.h已经自动包含了它。
在这个头文件中声明了若干个类,包括ifstream,ofstream及fstream,它们都继承自istream和ostream类。
ofstreamSaveFile(“cpp-home.txt”);
1)ofstream即“outputfilestream(输出文件流)”。
它将建立一个句柄(handle),以便我们以后能以一个文件流的形式写入文件。
2)SaveFile——这是文件句柄的名字,当然,你还可以换用任何一个你想要的名称。
3)(“cpp-home.txt”);——打开名为cpp-home.txt的文件。
如果程序运行的当前目录已经存在这样一个文件,则它将被替换掉;万一不存在,程序也会为你创建一个为文件,你不必为此而担心。
现在,让我们稍微深入一点点。
首先,我要指出的是:
ofstream是一个类。
因此ofstreamSaveFile(“cpp-home.txt”);这一语句将创建一个该类的对象;而我们在括号中所传递的参数实际上将传给构造函数:
在这里我们将我们要建立的文件的名称作为实际参数传递给了该类的构造函数。
当然,我们还可以传递其它的一些信息,不过我以后再对其进行讲解。
SaveFile<<“HelloWorld,from.cpp-home.andLoobian!
”;——“<<”看起来是不是很亲切?
不错,想必你已经在cout<<中见到过。
这是一个预定义好的运算符。
不管怎么说,这行语句所做的,是将上面的那段文本写入文件。
正如前面所提到的,SaveFile是一个文件句柄,它关联一个打开的流式文件。
所以,我们只须输入句柄名,再跟着输入“<<”,然后接着写下一串用引号括起来的文本,就可以实现对文件的写入。
如果我们想写入的是某个变量的值而不是带引号的文本,也只须像通常使用cout<<一样将变量传递给句柄对象,像这样:
SaveFile< 就可以了! SaveFile.close();——既然我们打开了一个流文件,那么当我们用完它之后,就必须关闭它。 SaveFile是ofstream类的一个对象,而该类(ofstream)有一个用于关闭文件的成员函数,即close()函数。 因此,我们只要依次输入文件句柄名,点号和close(),就可以关闭该文件! 注意: 一旦你关闭文件,在你重新打开它以前,就再不能对它进行访问。 以上就是一个可以写文件的最简单程序。 的确很容易! 不过,正如你即将在以后部分的教程中所看到的,还有更多的东西要学呢! 本文引用通告地址: ================= C++中的文件输入/输出 (2): 读取文件 C++中的文件输入/输出 (2) 原作: IliaYordanov, loobiancpp-home. 读取文件 你已经看到了应该如何写文件。 现在,当我们已经得到cpp-home.txt文件时,我们将要读取它,并且将容打印在屏幕上。 首先,我要指出的是,有很多种方法可以读取文件。 以后我会向你们介绍所有的方法(就我所知的)。 此刻,我先向你展示最佳的方法(我认为的)。 正如你已经熟悉的——我将首先给出一段程序代码,然后,我会详细地对它进行解释说明: #include voidmain()//程序从这里开始 { ifstreamOpenFile("cpp-home.txt"); charch; while(! OpenFile.eof()) { OpenFile.get(ch); cout< } OpenFile.close(); } 你想必已经了解首行的意义所在,而剩下的部分将由我为你解释。 ifstreamOpenFile(“cpp-home.txt”)——我猜它对现在的你而言多少会熟悉些! ifstream表示“inputfilestream(输入文件流)”。 在前一节的程序中,出现的则是ofstream,它的意义是“outputfilestream(输出文件流)”。 前一节的程序是进行文件的写操作,这就是它用“output(输出)”来表示的原因。 而本节的程序则是读取一个文件,这就是它用“input(输入)”来表示的原因。 这一行剩下的代码于你而言应当是熟悉的了: OpenFile是ifstream类的一个对象,它将关联一个输入文件流;而用引号括住的容,就是将要打开的文件的名称。 请注意: 这里没有对要打开的文件是否存在进行测试! 以后我将向你指出如何进行检测。 charch;——声明一个字符数组(arrayoftypechar)。 只是有一点要提醒你: 这样的数组(arrays)只能存储一个ASCII字符。 while(! OpenFile.eof())——如果已经到达文件末尾,eof()函数将返回一个非零值。 因此我们所设计的这个循环将一直持续,直至我们的文件操作到达文件末尾。 这样我们就可以遍历整个文件,以便对它进行读取。 OpenFile.get(ch);——OpenFile是类ifstream的一个对象。 该类声明了一个名为get()的成员函数。 只要我们拥有该对象,我们自然就可以调用这个函数。 get()函数从相应的流文件中读出一个字符,并将其返回给变量。 在本例中,get()函数只带一个参数——用于存储所读取的字符的变量。 所以,调用OpenFile.get(ch)后程序将会从OpenFile流中读取一个字符并存入变量ch中。 注意: 如果你再次调用该函数,它将读取下一个字符,而不是原来的那一个! 你过后将理解为什么会这样。 这就是我们要不断反复循环直至读操作到达文件尾的原因。 每循环一次,我们将读出一个字符并将它保存在ch中。 cout<< ch;——显示ch变量值,它保存了读取得到的字符。 File.close();——我们打开了一个流式文件,就需要关闭它。 使用close()函数即可将它关闭,这和前一节的一样! 注意: 一旦你关闭了一个文件,在你重新打开它之前,你不能再对它进行访问。 大功告成了! 我希望你能明白我的解释。 当你编译并运行这个程序的时候,它应当会输出: “HelloWorld,from.cpp-home.andLoobian! ” 本文引用通告地址: =============== C++中的文件输入/输出(3): 掌握输入/输出流 C++中的文件输入/输出(3) 原作: IliaYordanov, loobiancpp-home. 掌握输入/输出流 在这一章里,我会提及一些有用的函数。 我将为你演示如何打开一个可以同时进行读、写操作的文件;此外,我还将为你介绍其它打开文件的方法,以及如何判断打开操作是否成功。 因此,请接着往下读! 到目前为止,我已为你所展示的只是单一的打开文件的途径: 要么为读取而打开,要么为写入而打开。 但文件还可以以其它方式打开。 迄今,你应当已经认识了下面的方法: ifstreamOpenFile(“cpp-home.txt”); 噢,这可不是唯一的方法! 正如以前所提到的,以上的代码创建一个类ifstream的对象,并将文件的名字传递给它的构造函数。 但实际上,还存在有不少的重载的构造函数,它们可以接受不止一个的参数。 同时,还有一个open()函数可以做同样的事情。 下面是一个以上代码的示例,但它使用了open()函数: ifstreamOpenFile; OpenFile.open(“cpp-home.txt”); 你会问: 它们之间有什么区别吗? 哦,我曾做了不少测试,结论是没有区别! 只不过如果你要创建一个文件句柄但不想立刻给它指定一个文件名,那么你可以使用open()函数过后进行指定。 顺便再给出一个要使用open()函数的例子: 如果你打开一个文件,然后关闭了它,又打算用同一个文件句柄打开另一个文件,这样一来,你将需要使用open()函数。 考虑以下的代码示例: #include voidread(ifstream&T)//passthefilestreamtothefunction { //themethodtoreadafile,thatIshowedyoubefore charch; while(! T.eof()) { T.get(ch); cout< } cout< } voidmain() { ifstreamT("file1.txt"); read(T); T.close(); T.open("file2.txt"); read(T); T.close(); } 据此,只要file1.txt和file2.txt并存储了文本容,你将看到这些容。 现在,该向你演示的是,文件名并不是你唯一可以向open()函数或者构造函数(其实都一样)传递的参数。 下面是一个函数原型: ifstreamOpenFile(char*filename,intopen_mode); 你应当知道filename表示文件的名称(一个字符串),而新出现的则是open_mode(打开模式)。 open_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 voidmain() { ofstreamSaveFile("file1.txt",ios: : ate); SaveFile<<"That'snew! \n"; SaveFile.close(); } 正如你在表中所看到的: 使用ios: : ate将会从文件的末尾开始执行写入。 如果我没有使用它,原来的文件容将会被重新写入的容覆盖掉。 不过既然我已经使用了它,那么我只会在原文件的末尾进行添加。 所以,如果file1.txt原有的容是这样: Hi! Thisistestfrom.cpp-home.! 那么执行上面的代码后,程序将会为它添上“That’snew! ”,因此它看起来将变成这样: Hi! Thisistestfrom.cpp-home.! That’snew! 假如你打算设置不止一个的打开模式标志,只须使用OR操作符或者是|,像这样: ios: : ate|ios: : binary 我希望现在你已经明白“打开模式”是什么意思了! 现在,是时候向你展示一些真正有用的东西了! 我敢打赌你现在还不知道应当怎样打开一个可以同时进行读取和写入操作的文件! 下面就是实现的方法: fstreamFile(“cpp-home.txt”,ios: : in|ios: : out); 实际上,这只是一个声明语句。 我将在下面数行之后给你一个代码示例。 但此时我首先想提及一些你应当知道的容。 上面的代码创建了一个名为“File”的流式文件的句柄。 如你所知,它是fstream类的一个对象。 当使用fstream时,你应当指定ios: : in和ios: : out作为文件的打开模式。 这样,你就可以同时对文件进行读、写,而无须创建新的文件句柄。 噢,当然,你也可以只进行读或者写的操作。 那样的话,相应地你应当只使用ios: : in或者只使用ios: : out——要思考的问题是: 如果你打算这么做,为什么你不分别用ifstream及ofstream来实现呢? 下面就先给出示例代码: #include voidmain() { fstreamFile("test.txt",ios: : in|ios: : out); File<<"Hi! ";//将“Hi! ”写入文件 staticcharstr[10];//当使用static时,数组会自动被初始化 //即是被清空为零 File.seekg(ios: : beg);//回到文件首部 //此函数将在后面解释 File>>str; cout< File.close(); } OK,这儿又有一些新东西,所以我将逐行进行解释: fstreamFile(“test.txt”,ios: : in|ios: : out);——此行创建一个fstream对象,执行时将会以读/写方式打开test.txt文件。 这意味着你可以同时读取文件并写入数据。 File<<“Hi! ”;——我打赌你已经知道它的意思了。 staticcharstr[10];——这将创建一个容量为10的字符数组。 我猜static对你而言或者有些陌生,如果这样就忽略它。 这只不过会在创建数组的同时对其进行初始化。 File.seekg(ios: : beg);——OK,我要让你明白它究竟会做些什么,因此我将以一些有点儿离题、但挺重要的容开始我的解释。 还记得它么: while(! OpenFile.eof()) { OpenFile.get(ch); cout< } 你是不是曾经很想知道那背后真正执行了什么操作? 不管是或不是,我都将为你解释。 这是一个while型循环,它会一直反复,直至程序的操作到达文件的尾端。 但这个循环如何知道是否已经到了文件末尾? 嗯,当你读文件的时候,会有一个类似于“置指针(inside-pointer)”的东西,它表明你读取(写入也一样)已经到了文件的哪个位置,就像记事本中的光标。 而每当你调用OpenFile.get(ch)的时候,它会返回当前位置的字符,存储在ch变量中,并将这一置指针向前移动一个字符。 因此下次该函数再被调用时,它将会返回下一个字符。 而这一过程将不断反复,直到读取到达文件尾。 所以,让我们回到那行代码: 函数seekg()将把置指针定位到指定的位置(依你决定)。 你可以使用: ios: : beg——可将它移动到文件首端 ios: : end——可将它移动到文件末端 或者,你可以设定向前或向后跳转的字符数。 例如,如果你要向定位到当前位置的5个字符以前,你应当写: File.seekg(-5); 如果你想向后跳过40个字符,则应当写: File.seekg(40); 同时,我必须指出,函数seekg()是被重载的,它也可以带两个参数。 另一个版本是这样子的: File.seekg(-5,ios: : end); 在这个例子中,你将能够读到文件文本的最后4个字符,因为: 1)你先到达了末尾(ios: : end) 2)你接着到达了末尾的前五个字符的位置(-5) 为什么你会读到4个字符而不是5个? 噢,只须把最后一个看成是“丢掉了”,因为文件最末端的“东西”既不是字符也不是空白符,那只是一个位置(译注: 或许ios: : end所“指”的根本已经超出了文件本身的围,确切的说它是指向文件最后一个字符的下一个位置,有点类似STL中的各个容器的end迭代点是指向最后一个元素的下一位置。 这样设计可能是便于在循环中实现遍历)。 你现在可能想知道为什么我要使用到这个函数。 呃,当我把“Hi”写进文件之后,置指针将被设为指向其后面……也就是文件的末尾。 因此我必须将置指针设回文件起始处。 这就是这个函数在此处的确切用途。 File>>str;——这也是新鲜的玩意儿! 噢,我确信这行代码让你想起了cin>>.实际上,它们之间有着相当的关联。 此行会从文件中读取一个单词,然后将它存入指定的数组变量中。 例如,如果文件中有这样的文本片断: Hi! Doyouknowme? 使用File>>str,则只会将“Hi! ”输出到str数组中。 你应当已经注意到了,它实际上是将空格作为单词的分隔符进行读取的。 由于我存入文件中的只是单独一个“Hi! ”,我不需要写一个while循环,那会花费更多的时间来写代码。 这就是我使用此方法的原因。 顺便说一下,到目前为止,我所使用的读取文件的while循环中,程序读文件的方式是一个字符一个字符进行读取的。 然而你也可以一个单词一个单词地进行读取,像这样: charstr[30];//每个单词的长度不能超过30个字符 while(! OpenFile.eof()) { OpenFile>>str; cout< } 你也可以一行一行地进行读取,像这样: charline[100];//每个整行将会陆续被存储在这里 while(! OpenFile.eof()) { OpenFile.getline(line,100);//100是数组的大小 cout< } 你现在可能想知道应当使用哪种方法。 嗯,我建议你使用逐行读取的方式,或者是最初我提及的逐字符读取的方式。 而逐词读取的方式并非一个好的方案,因为它不会读出新起一行这样的信息,所以如果你的文件中新起一行时,它将不会将那些容新起一行进行显示,而是加在已经打印的文本后面。 而使用getline()或者get()都将会向你展现出文件的本来面目! 现在,我将向你介绍如何检测文件打开操作是否成功。 实现上,好的方法少之又少,我将都会涉及它们。 需要注意的是,出现“X”的时候,它实际可以以“o”、“i”来代替,或者也可以什么都不是(那将是一个fstream对象)。 例1: 最通常的作法 XfstreamFile(“cpp-home.txt”); if(! File) { cout<<“Erroropeningthefile! Aborting…\n”; exit (1); } 例2: 如果文件已经被创建,返回一个错误 ofstreamFile("unexisting.txt",ios: : nocreate); if(! File) { cout<<“Erroropeningthefile! Aborting…\n”; exit (1); } 例3: 使用fail()函数 ofstreamFile("filer.txt",ios: : nocreate); if(File.fail()) { cout<<“Erroropeningthefile! Aborting…\n”; exit (1); } 例3中的新出现的东西,是fail()函数。 如果有任何输入/输出错误(不是在文件末尾)发生,它将返回非零值。 我也要讲一些我认为非常重要的容! 例如,如果你已经创建一个流文件对象,但你没有进行打开文件操作,像这样: ifstreamFile;//也可以是一个ofstream 这样,我们就拥有一个文件句柄,但我们仍然没有打开文件。 如果你打算迟些打开它,那么可以用open()函数来实现,我已经在本教程中将它介绍了。 但如果在你的程序的某处,你可能需要知道当前的句柄是否关联了一个已经打开的文件,那么你可以用is_open()来进行检测。 如果文件没有打开,它将返回0(false);如果文件已经打开,它将返回1(true)。 例如: ofstreamFile1; File1.open("file1.txt"); cout< 上面的代码将会返回1(译注: 指File1.is_open()函数,下句同),因为我们已经打开了一个文件(在第二行)。 而下面的代码则会返回0,这是由于我们没有打开文件,而只是创建了一个流文件句柄: ofstreamFile1; cout< 好啦,这一章讲得够多啦。 本文引用通告地址: ================== C++中的文件输入/输出(4): 检测输入/输出的状态标志 C++中的文件输入/输出(4) 原作: IliaYordanov, loobiancpp-home.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C+ 文件 输入输出 讲解 非常 清晰