1. gzyueqian
      18529173453
      首頁 > 新聞中心 > > 正文

      C++中的文件輸入/輸出

      更新時間: 2007-05-25 14:38:25來源: 粵嵌教育瀏覽量:2034

       
        摘要:本文將以C++基本的文件I/O(輸出/輸出)開始。此后,我將從更深入的方面,為你展示一些技巧,并分析給出一些有用的函數。

        你需要對C++有一個較好的理解,否則這個教程于你而言將是陌生而毫無用處。

      你的個程序

      首先我將給出一段代碼,接著再逐行進行解釋。我們的個程序將建立一個文件,并寫入一些字符:

      #include

      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!”。

      下面給出各行的含義:

        #include —— 你需要包含此文件以使用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)
      來自loobian@cpp-home.com 作者Ilia Yordanov

        讀取文件

        你已經看到了應該如何寫文件?,F在,當我們已經得到cpp-home.txt文件時,我們將要讀取它,并且將內容打印在屏幕上。

        首先,我要指出的是,有很多種方法可以讀取文件。以后我會向你們介紹所有的方法(就我所知的)。此刻,我先向你展示的方法(我認為的)。

        正如你已經熟悉的——我將首先給出一段程序代碼,然后,我會詳細地對它進行解釋說明:

      #include
      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!”

      //////////////////////////////////////////////////////////////////////////////////////////////////////////

      Tomorrow0 (2003-8-22 10:08:35) :這段代碼運行后為什么在文件末尾會重復一個字符?

        經過測試確有如Tomorrow0所說的問題,原文(英文版作者)的確有一點小小的漏洞,eof()返回true的條件是“讀到文件結束符”,而非文件內容的一個字符。所以讀完“3”以后,由于“3”并非文件結束符,所以eof()返回false值,繼續讀讀到文件結束符(大概就是eqiaotea所說的0xff)后eof()才返回true,也就是多讀了一次。有些編譯器(像DEV C++,其實也就是GNU C++)讀到一個字符后文件位置的指針會定在那兒,所以就成了TOMORROW0所說的“重復一個字符”。我給出一個參考解決的方法是,將源代碼片斷: while(!OpenFile.eof()) { OpenFile.get(ch); cout << ch; } 改為: while(OpenFile.get(ch)) cout << ch; 這是因為OpenFile.get()函數當讀到文件結束符時會返回false值(否則返回true),因而就不會打印出無用的結束符(或重復前一字符),也不需要使用eof()判斷了。 感謝指出此問題。

        掌握輸入/輸出流

        在這一章里,我會提及一些有用的函數。我將為你演示如何打開一個可以同時進行讀、寫操作的文件;此外,我還將為你介紹其它打開文件的方法,以及如何判斷打開操作是否成功。因此,請接著往下讀!

        到目前為止,我已為你所展示的只是單一的打開文件的途徑:要么為讀取而打開,要么為寫入而打開。但文件還可以以其它方式打開。迄今,你應當已經認識了下面的方法:

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

        噢,這可不是的方法!正如以前所提到的,以上的代碼創建一個類ifstream的對象,并將文件的名字傳遞給它的構造函數。但實際上,還存在有不少的重載的構造函數,它們可以接受不止一個的參數。同時,還有一個open()函數可以做同樣的事情。下面是一個以上代碼的示例,但它使用了open()函數:

      ifstream OpenFile;

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

        你會問:它們之間有什么區別嗎?哦,我曾做了不少測試,結論是沒有區別!只不過如果你要創建一個文件句柄但不想立刻給它指定一個文件名,那么你可以使用open()函數過后進行指定。順便再給出一個要使用open()函數的例子:如果你打開一個文件,然后關閉了它,又打算用同一個文件句柄打開另一個文件,這樣一來,你將需要使用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(!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常量。但為了讓你的編程生涯不至于太痛苦,你可以像上表所見的那樣使用那些名稱。

      下面是一個關于如何使用打開模式的例子:

      #include

      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來實現呢?

      下面就先給出示例代碼:

      #include

      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()是被重載的,它也可以帶兩個參數。另一個版本是這樣子的:

      File.seekg(-5,ios::end);

      在這個例子中,你將能夠讀到文件文本的4個字符,因為:

        1)你先到達了末尾(ios::end)

        2)你接著到達了末尾的前五個字符的位置(-5)

        為什么你會讀到4個字符而不是5個?噢,只須把一個看成是“丟掉了”,因為文件末端的“東西”既不是字符也不是空白符,那只是一個位置(譯注:或許ios::end所“指”的根本已經超出了文件本身的范圍,確切的說它是指向文件一個字符的下一個位置,有點類似STL中的各個容器的end迭代點是指向一個元素的下一位置。這樣設計可能是便于在循環中實現遍歷)。

        你現在可能想知道為什么我要使用到這個函數。呃,當我把“Hi”寫進文件之后,內置指針將被設為指向其后面……也就是文件的末尾。因此我必須將內置指針設回文件起始處。這就是這個函數在此處的確切用途。

        File >> str; —— 這也是新鮮的玩意兒!噢,我確信這行代碼讓你想起了cin >> .實際上,它們之間有著相當的關聯。此行會從文件中讀取一個單詞,然后將它存入指定的數組變量中。

      例如,如果文件中有這樣的文本片斷:

      Hi! Do you know me?

        使用File >> str,則只會將“Hi!”輸出到str數組中。你應當已經注意到了,它實際上是將空格作為單詞的分隔符進行讀取的。

        由于我存入文件中的只是單獨一個“Hi!”,我不需要寫一個while循環,那會花費更多的時間來寫代碼。這就是我使用此方法的原因。順便說一下,到目前為止,我所使用的讀取文件的while循環中,程序讀文件的方式是一個字符一個字符進行讀取的。然而你也可以一個單詞一個單詞地進行讀取,像這樣:

      char str[30]; // 每個單詞的長度不能超過30個字符

      while(!OpenFile.eof())
      {
      OpenFile >> str;
      cout << str;
      }

      你也可以一行一行地進行讀取,像這樣:

      char line[100]; // 每個整行將會陸續被存儲在這里
      while(!OpenFile.eof())
      {
      OpenFile.getline(line,100); // 100是數組的大小
      cout << line << endl;
      }

        你現在可能想知道應當使用哪種方法。嗯,我建議你使用逐行讀取的方式,或者是初我提及的逐字符讀取的方式。而逐詞讀取的方式并非一個好的方案,因為它不會讀出新起一行這樣的信息,所以如果你的文件中新起一行時,它將不會將那些內容新起一行進行顯示,而是加在已經打印的文本后面。而使用getline()或者get()都將會向你展現出文件的本來面目!

      現在,我將向你介紹如何檢測文件打開操作是否成功。實現上,好的方法少之又少,我將都會涉及它們。需要注意的是,出現“X”的時候,它實際可以以“o”、 “i”來代替,或者也可以什么都不是(那將是一個fstream對象)。

      例1:通常的作法

      Xfstream File(“cpp-home.txt”);
      if (!File)
      {
      cout << “Error opening the file! Aborting…\n”;
      exit(1);
      }

      例2:如果文件已經被創建,返回一個錯誤

      ofstream File("unexisting.txt", ios::nocreate);

      if(!File)
      {
      cout << “Error opening the file! Aborting…\n”;
      exit(1);
      }

      例3:使用fail()函數

      ofstream File("filer.txt", ios::nocreate);

      if(File.fail())
      {
      cout << “Error opening the file! Aborting…\n”;
      exit(1);
      }

        例3中的新出現的東西,是fail()函數。如果有任何輸入/輸出錯誤(不是在文件末尾)發生,它將返回非零值。我也要講一些我認為非常重要的內容!例如,如果你已經創建一個流文件對象,但你沒有進行打開文件操作,像這樣:

      ifstream File; //也可以是一個ofstream

        這樣,我們就擁有一個文件句柄,但我們仍然沒有打開文件。如果你打算遲些打開它,那么可以用open()函數來實現,我已經在本教程中將它介紹了。但如果在你的程序的某處,你可能需要知道當前的句柄是否關聯了一個已經打開的文件,那么你可以用is_open()來進行檢測。如果文件沒有打開,它將返回0 (false);如果文件已經打開,它將返回1 (true)。例如:

      ofstream File1;

      File1.open("file1.txt");

      cout << File1.is_open() << endl;

      上面的代碼將會返回1(譯注:指File1.is_open()函數,下句同),因為我們已經打開了一個文件(在第二行)。而下面的代碼則會返回0,這是由于我們沒有打開文件,而只是創建了一個流文件句柄:

      ofstream File1;

      cout << File1.is_open() << endl;


        檢測輸入/輸出的狀態標志

        在此我不打算解釋“標志(flags)”一詞的含義,不過假如你真的完全不理解關于這方面的概念,那么將本章讀過一遍之后也許你對此會得到一些認識,我也相信你同樣能理解這部分的理論。盡管如此,如果你還是不明白標志在C++中的含義,我推薦你閱讀一些關于這個主題的資料。好,讓我們開始吧。

        C++中負責的輸入/輸出的系統包括了關于每一個輸入/輸出操作的結果的記錄信息。這些當前的狀態信息被包含在io_state類型的對象中。io_state是一個枚舉類型(就像open_mode一樣),以下便是它包含的值(譯注:表中列為枚舉值的名稱,第二列為該值相應含義的描述):

      godbit
      無錯誤

      Eofbit
      已到達文件尾

      failbit
      非致命的輸入/輸出錯誤

      badbit
      致使的輸入/輸出錯誤

        有兩種方法可以獲得輸入/輸出的狀態信息。一種方法是通過調用rdstate()函數,它將返回當前狀態的錯誤標記(上表中提到的)。例如,假如沒有任何錯誤,則rdstate()會返回goodbit.另一種方法則是使用下面任何一個函數來檢測相應的輸入/輸出狀態:

      bool bad();
      bool eof(); //還記得它么?“不斷讀取文件內容直到到達文件末尾!”
      bool fail(); //噢,這也是老朋友……檢測一個打開操作是否成功
      bool good();

        假如badbit標志被標設(譯注:原文為“If the badbit flag is up”,這里將“is up”譯為“標設”,意即出現了badbit對應的錯誤,badbit狀態被置為當前的錯誤狀態,下同),則bad()函數返回true;假如failbit標志被標設,則fail()函數返回true;假如沒有錯誤發生(goodbit標志被標設),則good()函數返回true;假如操作已經到達了文件末尾(eofbit被標設),則eof()函數返回true.

        如果錯誤發生,你必須清除這些錯誤狀態,以使你的程序能正確適當地繼續運行——如果你這么打算的話。要清除錯誤狀態,需使用clear()函數。此函數帶一個參數,它是你將要設為當前狀態的標志值。假使你想讓你的程序“清清爽爽”地運行下去,只要將ios::goodbit作為實參。你將在以下內容中看到示例代碼。

      我將向你展示示例代碼,以鞏固你所學到的理論知識。
      示例1:簡單的狀態檢測
      // 實際應用中可將 FileStream替換成你相應在使用的文件流句柄

      if(FileStream.rdstate() == ios::eofbit)
      cout << "End of file!\n";
      if(FileStream.rdstate() == ios::badbit)
      cout << "Fatal I/O error!\n";
      if(FileStream.rdstate() == ios::failbit)
      cout << "Non-fatal I/O error!\n";
      if(FileStream.rdstate() == ios::goodbit)
      cout << "No errors!\n";

      示例2:clear()函數
      #include
      void main()
      {
      ofstream File1("file2.txt"); //建立file2.txt
      File1.close();

      // 下面的檢測代碼將會返回錯誤,這是因為我使用了ios::noreplace打開模式
      // 它模式在試圖打開一個已存在的文件時會返回錯誤
      ofstream Test("file2.txt",ios::noreplace);
      // 上一行將導致ios::failbit錯誤,我們這就將其演示出來
      if(Test.rdstate() == ios::failbit)
      cout << "Error...!\n";

      Test.clear(ios::goodbit); // 將當前狀態重置為ios::goodbit
      if(Test.rdstate() == ios::goodbit) // 檢測程序是否已經正確地施行了設置
      cout << "Fine!\n";
      Test.clear(ios::eofbit); // 將狀態標志設為ios::eofbit. 無實際用途.

      if(Test.rdstate() == ios::eofbit) // 檢測是否已經正確地施行了設置 cout << "EOF!\n";
      Test.close();
      }

        除了使用標記值判斷,你也可以使用函數(譯注:指bad()、eof()、fail()、good()這些函數)的形式進行判斷,兩者實際上是一樣的——都是檢測某個標記是否被標設。這些函數前面已經介紹過,我就不再重復了。如果你對如何使用它們還不是十分確定,那就重新回顧一下本教程中我曾經為你演示的應該如何檢測一個文件打開操作是否成功的那部分內容。在那里我就使用了fail()函數。

      C++中的文件輸入/輸出(5)
      原作:Ilia Yordanov, loobian@cpp-home.com

        二進制文件的處理

        雖然有規則格式(formatted)的文本(到目前為止我所討論的所有文件形式)非常有用,但有時候你需要用到無格式(unformatted)的文件——二進制文件。它們和你的可執行程序看起來一樣,而與使用<<及>>操作符創建的文件則大不相同。get()函數與put()函數則賦予你讀/寫無規則格式文件的能力:要讀取一個字節,你可以使用get()函數;要寫入一個字節,則使用put()函數。你應當回想起get()——我曾經使用過它。你可能會疑惑為什么當時我們使用它時,輸出到屏幕的文件內容看起來是文本格式的?嗯,我猜這是因為我此前使用了<<及>>操作符。

        譯注:作者的所謂“規則格式文本(formatted text)”即我們平時所說的文本格式,而與之相對的“無格式文件(unformatted files)”即以存儲各類數據或可執行代碼的非文本格式文件。通常后者需要讀入內存,在二進制層次進行解析,而前者則可以直接由預定好的<<及>>操作符進行讀入/寫出(當然,對后者也可以通過恰當地重載<<及>>操作符實現同樣的功能,但這已經不是本系列的討論范圍了)。

        get()函數與都各帶一個參數:一個char型變量(譯注:指get()函數)或一個字符(譯注:指put()函數,當然此字符也可以以char型變量提供)。

      假如你要讀/寫一整塊的數據,那么你可以使用read()和write()函數。它們的原型如下:

      istream &read(char *buf, streamsize num);
      ostream &write(const char *buf, streamsize num);

        對于read()函數,buf應當是一個字符數組,由文件讀出的數據將被保存在這兒。對于write()函數,buf是一個字符數組,它用以存放你要寫入文件的數據。對于這兩個函數,num是一個數字,它指定你要從文件中讀取/寫入的字節數。

        假如在讀取數據時,在你讀取“num”個字節之前就已經到達了文件的末尾,那么你可以通過調用gcount()函數來了解實際所讀出的字節數。此函數會返回一次進行的對無格式文件的讀入操作所實際讀取的字節數。

        在給出示例代碼之前,我要補充的是,如果你要以二進制方式對文件進行讀/寫,那么你應當將ios::binary作為打開模式加入到文件打開的參數表中。

      現在就讓我向你展示示例代碼,你會看到它是如何運作的。

      示例1:使用get( )和put( )
      #include
      void main()
      {
      fstream File("test_file.txt",ios::out | ios::in | ios::binary);
      char ch;
      ch='o';
      File.put(ch); // 將ch的內容寫入文件
      File.seekg(ios::beg); // 定位至文件首部
      File.get(ch); // 讀出一個字符
      cout << ch << endl; // 將其顯示在屏幕上
      File.close();
      }

      示例2:使用read( )和write( )
      #include
      #include
      void main()
      {
      fstream File("test_file.txt",ios::out | ios::in | ios::binary);
      char arr[13];
      strcpy(arr,"Hello World!"); //將Hello World!存入數組
      File.write(arr,5); // 將前5個字符——"Hello"寫入文件
      File.seekg(ios::beg); // 定位至文件首部
      static char read_array[10]; // 在此我將打算讀出些數據
      File.read(read_array,3); // 讀出前三個字符——"Hel"
      cout << read_array << endl; // 將它們輸出
      File.close();
      }

      免費預約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 亚洲国产无色码在线播放 | 亚洲国产品综合人成综合网站 | 日韩R级网站在线观看 | 一区二区三区国产日韩 | 一级Av中文字幕 | 日韩专区亚洲精品 |