c++文件输入输出

C++中的文件输入/输出(1):你的第一个程序      

   简介  

    本教程将以C++最基本的文件I/O(输出/输出)开始。此后,我将从更深入的方面,为你展示一些技巧,并分析给出一些有用的函数。

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

   你的第一个程序 

   首先我将给出一段代码,接着再逐行进行解释。我们的第一个程序将建立一个文件,并写入一些字符:  

#i nclude   

void main() // 程序从这里开始运行   

{   

     ofstream SaveFile(“cpp-home.txt”);  

    SaveFile << “Hello World, from www.cpp-home.com and Loobian!”;   

     SaveFile.close();   

}   

仅仅如此吗?没错!这个程序将在当前运行目录下建立一个名为cpp-home.txt的文件,并向它写入“Hello World, from www.cpp-home.com and Loobian!”。  

   下面给出各行的含义:  

   #i nclude —— 你需要包含此文件以使用C++的文件输入/输出函数。注意:一旦包含了这个文件,你不再需要(为了使用cout/cin)包含iostream.h,因为fstream.h已经自动包含了它。  

    在这个头文件中声明了若干个类,包括ifstream,ofstream及fstream,它们都继承自istream和ostream类。  

    ofstream SaveFile(“cpp-home.txt”);  

   1)ofstream即“output file stream(输出文件流)”。它将建立一个句柄(handle),以便我们以后能以一个文件流的形式写入文件。 

   2)SaveFile —— 这是文件句柄的名字,当然,你还可以换用任何一个你想要的名称。   3)(“cpp-home.txt”); —— 打开名为cpp-home.txt的文件。如果程序运行的当前目录已经存在这样一个文件,则它将被替换掉;万一不存在,程序也会为你创建一个为文件,你不必为此而担心。  

    现在,让我们稍微深入一点点。首先,我要指出的是:ofstream是一个类。因此ofstream SaveFile(“cpp-home.txt”);这一语句将创建一个该类的对象;而我们在括号中所传递的参数实际上将传给构造函数:在这里我们将我们要建立的文件的名称作为实际参数传递给了该类的构造函数。当然,我们还可以传递其它的一些信息,不过我以后再对其进行讲解。  SaveFile << “Hello World, from www.cpp-home.com and Loobian!”; —— “<<”看起来是不是很亲切?不错,想必你已经在cout << 中见到过。这是一个预定义好的运算符。不管怎么说,这行语句所做的,是将上面的那段文本写入文件。正如前面所提到的,SaveFile是一个文件句柄,它关联一个打开的流式文件。所以,我们只须输入句柄名,再跟着输入“<<”,然后接着写下一串用引号括起来的文本,就可以实现对文件的写入。如果我们想写入的是某个变量的值而不是带引号的文本,也只须像通常使用cout << 一样将变量传递给句柄对象,像这样:

  SaveFile << variablename;  

   就可以了! 

   SaveFile.close(); —— 既然我们打开了一个流文件,那么当我们用完它之后,就必须关闭它。SaveFile是ofstream类的一个对象,而该类(ofstream)有一个用于关闭文件的成员函数,即close() 函数。因此,我们只要依次输入文件句柄名,点号和close(),就可以关闭该文件!  注意:一旦你关闭文件,在你重新打开它以前,就再不能对它进行访问。  以上就是一个可以写文件的最简单程序。的确很容易!不过,正如你即将在以后部分的教程中所看到的,还有更多的东西要学呢!

C++中的文件输入/输出(2):读取文件  

   读取文件  

    你已经看到了应该如何写文件。现在,当我们已经得到cpp-home.txt文件时,我们将要读取它,并且将内容打印在屏幕上。 

   首先,我要指出的是,有很多种方法可以读取文件。以后我会向你们介绍所有的方法(就我所知的)。此刻,我先向你展示最佳的方法(我认为的)。

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

#i nclude   

void main() //程序从这里开始   

{   

      ifstream OpenFile("cpp-home.txt");   

      char ch;   

      while(!OpenFile.eof())

   {   

          OpenFile.get(ch);  

         cout << ch;  

    }    OpenFile.close();  

}   

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

    ifstream OpenFile(“cpp-home.txt”) —— 我猜它对现在的你而言多少会熟悉些!ifstream表示“input file stream(输入文件流)”。在前一节的程序中,出现的则是ofstream,它的意义是“output file stream(输出文件流)”。前一节的程序是进行文件的写操作,这就是它用“output(输出)”来表示的原因。而本节的程序则是读取一个文件,这就是它用“input(输入)”来表示的原因。这一行剩下的代码于你而言应当是熟悉的了:OpenFile是ifstream类的一个对象,它将关联一个输入文件流;而用引号括住的内容,就是将要打开的文件的名称。  

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

   char ch; —— 声明一个字符数组(array of type char)。只是有一点要提醒你:这样的数组(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()函数即可将它关闭,这和前一节的一样! 

   注意:一旦你关闭了一个文件,在你重新打开它之前,你不能再对它进行访问。  大功告成了!我希望你能明白我的解释。当你编译并运行这个程序的时候,它应当会输出:   “Hello World, from www.cpp-home.com and Loobian!”

 

C++中的文件输入/输出(3):掌握输入/输出流    

    掌握输入/输出流  

    在这一章里,我会提及一些有用的函数。我将为你演示如何打开一个可以同时进行读、写操作的文件;此外,我还将为你介绍其它打开文件的方法,以及如何判断打开操作是否成功。因此,请接着往下读! 

   到目前为止,我已为你所展示的只是单一的打开文件的途径:要么为读取而打开,要么为写入而打开。但文件还可以以其它方式打开。迄今,你应当已经认识了下面的方法:

  ifstream OpenFile(“cpp-home.txt”);  

   噢,这可不是唯一的方法!正如以前所提到的,以上的代码创建一个类ifstream的对象,并将文件的名字传递给它的构造函数。但实际上,还存在有不少的重载的构造函数,它们可以接受不止一个的参数。同时,还有一个open()函数可以做同样的事情。下面是一个以上代码的示例,但它使用了open()函数:

  ifstream OpenFile;  

   OpenFile.open(“cpp-home.txt”);  

   你会问:它们之间有什么区别吗?哦,我曾做了不少测试,结论是没有区别!只不过如果你要创建一个文件句柄但不想立刻给它指定一个文件名,那么你可以使用 open()函数过后进行指定。顺便再给出一个要使用open()函数的例子:如果你打开一个文件,然后关闭了它,又打算用同一个文件句柄打开另一个文件,这样一来,你将需要使用open()函数。 

   考虑以下的代码示例:   

#i nclude   

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(!T.eof())  {  

           T.get(ch);   

            cout << ch;  

      }   

       cout << endl << "--------" << endl;  

 }  

 void main()  

 {   

         ifstream T("file1.txt");   

         read(T);   

         T.close();  

        T.open("file2.txt");  

        read(T);  

        T.close();  

 }   

    据此,只要file1.txt和file2.txt并存储了文本内容,你将看到这些内容。

  现在,该向你演示的是,文件名并不是你唯一可以向open()函数或者构造函数(其实都一样)传递的参数。下面是一个函数原型: 

   ifstream OpenFile(char *filename, int open_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常量。但为了让你的编程生涯不至于太痛苦,你可以像上表所见的那样使用那些名称。  

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

 #i nclude  

 void main()  

 {   

          ofstream SaveFile("file1.txt", ios::ate);  

         SaveFile << "That's new!\n";  

         SaveFile.close();  

 }   

    正如你在表中所看到的:使用ios::ate将会从文件的末尾开始执行写入。如果我没有使用它,原来的文件内容将会被重新写入的内容覆盖掉。不过既然我已经使用了它,那么我只会在原文件的末尾进行添加。所以,如果file1.txt原有的内容是这样:

  Hi! This is test from www.cpp-home.com!   那么执行上面的代码后,程序将会为它添上“That’s new!”,因此它看起来将变成这样:

  Hi! This is test from www.cpp-home.com!That’s new!   假如你打算设置不止一个的打开模式标志,只须使用OR操作符或者是 | ,像这样:

  ios::ate | ios::binary  

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

   现在,是时候向你展示一些真正有用的东西了!我敢打赌你现在还不知道应当怎样打开一个可以同时进行读取和写入操作的文件!下面就是实现的方法: 

   fstream File(“cpp-home.txt”,ios::in | ios::out);

  实际上,这只是一个声明语句。我将在下面数行之后给你一个代码示例。但此时我首先想提及一些你应当知道的内容。

  上面的代码创建了一个名为“File”的流式文件的句柄。如你所知,它是fstream类的一个对象。当使用fstream时,你应当指定ios:: in和ios::out作为文件的打开模式。这样,你就可以同时对文件进行读、写,而无须创建新的文件句柄。噢,当然,你也可以只进行读或者写的操作。那样的话,相应地你应当只使用ios::in或者只使用ios::out —— 要思考的问题是:如果你打算这么做,为什么你不分别用ifstream及ofstream来实现呢?  

    下面就先给出示例代码:  

#i nclude  

void main()  

{   

       fstream File("test.txt",ios::in | ios::out);    

       File << "Hi!"; //将“Hi!”写入文件   

       static char str[10]; //当使用static时,数组会自动被初始化    //即是被清空为零   

       File.seekg(ios::beg); // 回到文件首部    // 此函数将在后面解释  

       File >> str;   

       cout << str << endl;   

       File.close();   

}   

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

   fstream File(“test.txt”, ios::in | ios::out); —— 此行创建一个fstream对象,执行时将会以读/写方式打开test.txt文件。这意味着你可以同时读取文件并写入数据。     File << “Hi!”; —— 我打赌你已经知道它的意思了。  

   static char str[10]; —— 这将创建一个容量为10的字符数组。我猜static对你而言或者有些陌生,如果这样就忽略它。这只不过会在创建数组的同时对其进行初始化。

  File.seekg(ios::beg); —— OK,我要让你明白它究竟会做些什么,因此我将以一些有点儿离题、但挺重要的内容开始我的解释。  

   还记得它么: 

 while(!OpenFile.eof())   

{   

        OpenFile.get(ch);  

       cout << ch;   

 }  

   你是不是曾经很想知道那背后真正执行了什么操作?不管是或不是,我都将为你解释。这是一个while型循环,它会一直反复,直至程序的操作到达文件的尾端。但这个循环如何知道是否已经到了文件末尾?嗯,当你读文件的时候,会有一个类似于“内置指针(inside-pointer)”的东西,它表明你读取(写入也一样)已经到了文件的哪个位置,就像记事本中的光标。而每当你调用OpenFile.get(ch)的时候,它会返回当前位置的字符,存储在ch 变量中,并将这一内置指针向前移动一个字符。因此下次该函数再被调用时,它将会返回下一个字符。而这一过程将不断反复,直到读取到达文件尾。所以,让我们回到那行代码:函数seekg()将把内置指针定位到指定的位置(依你决定)。你可以使用:

  ios::beg —— 可将它移动到文件首端  

   ios::end —— 可将它移动到文件末端 

   或者,你可以设定向前或向后跳转的字符数。例如,如果你要向定位到当前位置的5个字符以前,你应当写: 

   File.seekg(-5);  

   如果你想向后跳过40个字符,则应当写:  

   File.seekg(40);  

   同时,我必须指出,函数seekg()是被重载的,它也可以带两个参数。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值