c++輸入和輸出流

1.流的概念和流類庫的結(jié)構(gòu)

  • 程序的輸入指的是從輸入文件將數(shù)據(jù)傳送給程序,程序的輸出指的是從程序?qū)?shù)據(jù)傳送給輸出文件。

  • C++輸入輸出包含以下三個方面的內(nèi)容:

      1. 對系統(tǒng)指定的標(biāo)準(zhǔn)設(shè)備的輸入和輸出。即從鍵盤輸入數(shù)據(jù),輸出到顯示器屏幕。這種輸入輸出稱為標(biāo)準(zhǔn)的輸入輸出,簡稱標(biāo)準(zhǔn)I/O。
      1. 以外存磁盤文件為對象進(jìn)行輸入和輸出,即從磁盤文件輸入數(shù)據(jù),數(shù)據(jù)輸出到磁盤文件。以外存文件為對象的輸入輸出稱為文件的輸入輸出,簡稱文件I/O。
      1. 對內(nèi)存中指定的空間進(jìn)行輸入和輸出。通常指定一個字符數(shù)組作為存儲空間(實際上可以利用該空間存儲任何信息)。這種輸入和輸出稱為字符串輸入輸出,簡稱串I/O。
  • C++編譯系統(tǒng)提供了用于輸入輸出的iostream類庫。iostream這個單詞是由3個部 分組成的,即i-o-stream,意為輸入輸出流。在iostream類庫中包含許多用于輸入輸出的 類。常用的見表

  • ios是抽象基類,由它派生出istream類和ostream類,兩個類名中第1個字母i和o分別代表輸入(input)和輸出(output)。 istream類支持輸入操作,ostream類支持輸出操作, iostream類支持輸入輸出操作。iostream類是從istream類和ostream類通過多重繼承而派生的類。其繼承層次見上圖表示。

  • C++對文件的輸入輸出需要用ifstream和ofstream類,兩個類名中第1個字母i和o分別代表輸入和輸出,第2個字母f代表文件 (file)。ifstream支持對文件的輸入操作, ofstream支持對文件的輸出操作。類ifstream繼承了類istream,類ofstream繼承了類ostream,類fstream繼承了 類iostream。見圖

  • I/O類庫中還有其他一些類,但是對于一般用戶來說,以上這些已能滿足需要了。
  • 與iostream類庫有關(guān)的頭文件

  • iostream類庫中不同的類的聲明被放在不同的頭文件中,用戶在自己的程序中用#include命令包含了有關(guān)的頭文件就相當(dāng)于在本程序中聲明了所需 要用到的類??梢該Q —種說法:頭文件是程序與類庫的接口,iostream類庫的接口分別由不同的頭文件來實現(xiàn)。常用的有
    ? iostream 包含了對輸入輸出流進(jìn)行操作所需的基本信息。
    ? fstream 用于用戶管理的文件的I/O操作。
    ? strstream 用于字符串流I/O。
    ? stdiostream 用于混合使用C和C + +的I/O機(jī)制時,例如想將C程序轉(zhuǎn)變?yōu)镃++程序。
    ? iomanip 在使用格式化I/O時應(yīng)包含此頭文件。
  • 在iostream頭文件中定義的流對象

  • 在 iostream 頭文件中定義的類有 ios,istream,ostream,iostream,istream 等。

  • 在iostream頭文件中不僅定義了有關(guān)的類,還定義了4種流對象,

對象 含義 對應(yīng)設(shè)備 對應(yīng)的類 c語言中相應(yīng)的標(biāo)準(zhǔn)文件
cin 標(biāo)準(zhǔn)輸入流 鍵盤 istream_withassign stdin
cout 標(biāo)準(zhǔn)輸出流 屏幕 ostream_withassign stdout
cerr 標(biāo)準(zhǔn)錯誤流 屏幕 ostream_withassign stderr
clog 標(biāo)準(zhǔn)錯誤流 屏幕 ostream_withassign stderr
  • 在iostream頭文件中定義以上4個流對象用以下的形式(以cout為例):
    ostream cout ( stdout);
  • 在定義cout為ostream流類對象時,把標(biāo)準(zhǔn)輸出設(shè)備stdout作為參數(shù),這樣它就與標(biāo)準(zhǔn)輸出設(shè)備(顯示器)聯(lián)系起來,如果有
    cout <<3;

就會在顯示器的屏幕上輸出3。
在iostream頭文件中重載運算符
“<<”和“>>”本來在C中是被定義為左位移運算符和右位移運算符的,由于在iostream頭文件中對它們進(jìn)行了重載, 使它們能用作標(biāo)準(zhǔn)類型數(shù)據(jù)的輸入和輸出運算符。所以,在用它們的程序中必須用#include命令把iostream包含到程序中。
#include <iostream>

1)  >>a表示將數(shù)據(jù)放入a對象中。
2)  <<a表示將a對象中存儲的數(shù)據(jù)拿出。

2.標(biāo)準(zhǔn)I/O流

  • 標(biāo)準(zhǔn)I/O對象:cin,cout,cerr,clog

  • cout流對象

  • cout是console output的縮寫,意為在控制臺(終端顯示器)的輸出。強調(diào)幾點。

    1. cout不是C++預(yù)定義的關(guān)鍵字,它是ostream流類的對象,在iostream中定義。 顧名思義,流是流動的數(shù)據(jù),cout流是流向顯示器的數(shù)據(jù)。cout流中的數(shù)據(jù)是用流插入運算符“<<”順序加入的。如果有:
    cout<<"I "<<"study C++ "<<"very hard. << “hello world !";

按順序?qū)⒆址?I ", "study C++ ", "very hard."插人到cout流中,cout就將它們送到顯示器,在顯示器上輸出字符串"I study C++ very hard."。

  • cout流是容納數(shù)據(jù)的載體,它并不是一個運算符。人們關(guān)心的是cout流中的內(nèi)容,也就是向顯示器輸出什么。
  1. 用“cout<<”輸出基本類型的數(shù)據(jù)時,可以不必考慮數(shù)據(jù)是什么類型,系統(tǒng)會判斷數(shù) 據(jù)的類型,并根據(jù)其類型選擇調(diào)用與之匹配的運算符重 載函數(shù)。這個過程都是自動的, 用戶不必干預(yù)。如果在C語言中用prinf函數(shù)輸出不同類型的數(shù)據(jù),必須分別指定相應(yīng)的輸出格式符,十分麻煩,而且容易出錯。C++的I/O機(jī)制對用戶來說,顯然是方便 而安全的。

  2. cout流在內(nèi)存中對應(yīng)開辟了一個緩沖區(qū),用來存放流中的數(shù)據(jù),當(dāng)向cout流插人一個endl時,不論緩沖區(qū)是否已滿,都立即輸出流中所有數(shù)據(jù),然后插入一個換行符, 并刷新流(清空緩沖區(qū))。注意如果插人一個換行符”\n“(如cout<<a<<"\n"),則只輸出和換行,而不刷新cout 流(但并不是所有編譯系統(tǒng)都體現(xiàn)出這一區(qū)別)。

  3. 在iostream中只對"<<"和">>"運算符用于標(biāo)準(zhǔn)類型數(shù)據(jù)的輸入輸出進(jìn)行了重載,但未對用戶聲明的類型數(shù)據(jù)的輸入輸出進(jìn)行重載。如果用戶聲明了新的類型,并希望用"<<"和">>"運算符對其進(jìn)行輸入輸出,按照重運算符重載來做。

  • cerr流對象

cerr流對象是標(biāo)準(zhǔn)錯誤流,cerr流已被指定為與顯示器關(guān)聯(lián)。cerr的 作用是向標(biāo)準(zhǔn)錯誤設(shè)備(standard error device)輸出有關(guān)出錯信息。

  • cerr與標(biāo)準(zhǔn)輸出流cout的作用和用法差不多。但有一點不同:cout流通常是傳送到顯示器輸出,但也可以被重定向輸出到磁盤文件,而cerr流中的信息只能在顯示器輸出。

  • 當(dāng)調(diào)試程序時,往往不希望程序運行時的出錯信息被送到其他文件,而要求在顯示器上及時輸出,這時應(yīng)該用cerr。cerr流中的信息是用戶根據(jù)需要指定的。

  • clog流對象

  • clog流對象也是標(biāo)準(zhǔn)錯誤流,它是console log的縮寫。它的作用和cerr相同,都是在終端顯示器上顯示出錯信息。

  • 區(qū)別:cerr是不經(jīng)過緩沖區(qū),直接向顯示器上輸出有關(guān)信息,而clog中的信息存放在緩沖區(qū)中,緩沖區(qū)滿后或遇endl時向顯示器輸出。

  • 緩沖區(qū)的概念

3.標(biāo)準(zhǔn)輸入流

  • 標(biāo)準(zhǔn)輸入流對象cin,重點掌握的函數(shù)
    • cin.get() //一次只能讀取一個字符
    • cin.get(一個參數(shù)) //讀一個字符
    • cin.get(兩個參數(shù)) //可以讀字符串
    • cin.getline()
    • cin.ignore()//忽略緩沖區(qū)當(dāng)前字符
    • cin.peek()//偷窺下緩沖區(qū)的數(shù)據(jù)
    • cin.putback()//將數(shù)據(jù)放回緩沖區(qū)
//cin.get
void test01(){
#if 0
    char ch = cin.get();
    cout << ch << endl;

    cin.get(ch);
    cout << ch << endl;


    //鏈?zhǔn)骄幊?    char char1, char2, char3, char4;
    cin.get(char1).get(char2).get(char3).get(char4);

    cout << char1 << " " << char2 << "" << char3 <<  " " << char4 << " ";
#endif

    char buf[1024] = { 0 };
    //cin.get(buf.1024);
    cin.getline(buf,1024);
    cout << buf;
}

//cin.ignore
void test02(){

    char buf[1024] = { 0 };
    cin.ignore(2); //忽略緩沖區(qū)當(dāng)前字符
    cin.get(buf,1024);
    cout << buf << endl;
}

//cin.putback 將數(shù)據(jù)放回緩沖區(qū)
void test03(){

    //從緩沖區(qū)取走一個字符
    char ch = cin.get();
    cout << "從緩沖區(qū)取走的字符:" << ch << endl;
    //將數(shù)據(jù)再放回緩沖區(qū)
    cin.putback(ch);
    char buf[1024] = { 0 };
    cin.get(buf,1024);
    cout << buf << endl;

}

//cin.peek 偷窺
void test04(){
    
    //偷窺下緩沖區(qū)的數(shù)據(jù)
    char ch = cin.peek();
    cout << "偷窺緩沖區(qū)數(shù)據(jù):" << ch << endl;
    char buf[1024] = { 0 };
    cin.get(buf, 1024);
    cout << buf << endl;
}

//練習(xí)  作業(yè) 使用cin.get和putback完成類似功能
void test05(){
    
    cout << "請輸入一個數(shù)字或者字符串:" << endl;
    char ch = cin.peek();
    if(ch >= '0' && ch <= '9'){
        int number;
        cin >> number;
        cout << "數(shù)字:" << number << endl;
    }
    else{
        char buf[64] = { 0 };
        cin.getline(buf, 64);
        cout << "字符串:" <<  buf << endl;
    }
}

4. 標(biāo)準(zhǔn)輸出流

  • 字符輸出

cout.flush() //刷新緩沖區(qū) Linux下有效
cout.put() //向緩沖區(qū)寫字符
cout.write() //從buffer中寫num個字節(jié)到當(dāng)前輸出流中。
//cout.flush 刷新緩沖區(qū),linux下有效
void test01(){  
    cout << "hello world";
    //刷新緩沖區(qū)
    cout.flush(); 
}

//cout.put 輸出一個字符
void test02(){
    
    cout.put('a');
    //鏈?zhǔn)骄幊?    cout.put('h').put('e').put('l');
}

//cout.write 輸出字符串 buf,輸出多少個
void test03(){
    
    //char* str = "hello world!";
    //cout.write(str, strlen(str));
    char* str = "*************";
    for (int i = 1; i <= strlen(str); i ++){
        cout.write(str, i);
        cout << endl;
    }

    for (int i = strlen(str); i > 0; i --){
        cout.write(str, i);
        cout << endl;
    }

}
  • 格式化輸出

  • 在輸出數(shù)據(jù)時,為簡便起見,往往不指定輸出的格式,由系統(tǒng)根據(jù)數(shù)據(jù)的類型采取默認(rèn)的格式,但有時希望數(shù)據(jù)按指定的格式輸出,如要求以十六進(jìn)制或八進(jìn)制形式輸出一個整數(shù),對輸出的小數(shù)只保留兩位小數(shù)等。有兩種方法可以達(dá)到此目的。

  • 1)使用控制符的方法;

  • 2)使用流對象的有關(guān)成員函數(shù)。

  • 使用流對象的有關(guān)成員函數(shù)

  • 通過調(diào)用流對象cout中用于控制輸出格式的成員函數(shù)來控制輸出格式。用于控制輸出格式的常用的成員函數(shù)如下:

  • 流成員函數(shù)setf和控制符setiosflags括號中的參數(shù)表示格式狀態(tài),它是通過格式標(biāo)志來指定的。格式標(biāo)志在類ios中被定義為枚舉值。因此在引用這些格式標(biāo)志時要在前面加上類名ios和域運算符“::”。
  • 控制符格式化輸出

  • C++提供了在輸入輸出流中使用的控制符(有的書中稱為操縱符)。

/通過流成員函數(shù)
void test01(){
    
    int number = 99;
    cout.width(20);
    cout.fill('*');
    cout.setf(ios::left);
    cout.unsetf(ios::dec); //卸載十進(jìn)制
    cout.setf(ios::hex);
    cout.setf(ios::showbase);
    cout.unsetf(ios::hex);
    cout.setf(ios::oct);
    cout << number << endl;

}

//使用控制符
void test02(){

    int number = 99;
    cout << setw(20)
        << setfill('~')
        << setiosflags(ios::showbase)
        << setiosflags(ios::left)
        << hex
        << number
        << endl;

}
  • 對程序的幾點說明
  1. 成員函數(shù)width(n)和控制符setw(n)只對其后的第一個輸出項有效。如:
cout. width(6);
cout <<20 <<3.14<<endl;
輸出結(jié)果為 203.14

在輸出第一個輸出項20時,域?qū)挒?,因此在20前面有4個空格,在輸出3.14時,width (6)已不起作用,此時按系統(tǒng)默認(rèn)的域?qū)捿敵觯ò磾?shù)據(jù)實際長度輸出)。如果要求在輸出數(shù)據(jù)時都按指定的同一域?qū)抧輸出,不能只調(diào)用一次width(n), 而必須在輸出每一項前都調(diào)用一次width(n),上面的程序中就是這樣做的。

  1. 在表13.5中的輸出格式狀態(tài)分為5組,每一組中同時只能選用一種(例如dec、hex和oct中只能選一,它們是互相排斥的)。在用成員函數(shù)setf和 控制符setiosflags設(shè)置輸出格式狀態(tài)后,如果想改設(shè)置為同組的另一狀態(tài),應(yīng)當(dāng)調(diào)用成員函數(shù)unsetf(對應(yīng)于成員函數(shù)self)或 resetiosflags(對應(yīng)于控制符setiosflags),先終止原來設(shè)置的狀態(tài)。然后再設(shè)置其他狀態(tài),大家可以從本程序中看到這點。程序在開 始雖然沒有用成員函數(shù)self和控制符setiosflags設(shè)置用dec輸出格式狀態(tài),但系統(tǒng)默認(rèn)指定為dec,因此要改變?yōu)閔ex或oct,也應(yīng)當(dāng)先 用unsetf 函數(shù)終止原來設(shè)置。如果刪去程序中的第7行和第10行,雖然在第8行和第11行中用成員函數(shù)setf設(shè)置了hex和oct格式,由于未終止dec格式,因 此hex和oct的設(shè)置均不起作用,系統(tǒng)依然以十進(jìn)制形式輸出。
    同理,程序倒數(shù)第8行的unsetf 函數(shù)的調(diào)用也是不可缺少的。

  2. 用setf 函數(shù)設(shè)置格式狀態(tài)時,可以包含兩個或多個格式標(biāo)志,由于這些格式標(biāo)志在ios類中被定義為枚舉值,每一個格式標(biāo)志以一個二進(jìn)位代表,因此可以用位或運算符“|”組合多個格式標(biāo)志。如倒數(shù)第5、第6行可以用下面一行代替:
    cout.setf(ios::internal I ios::showpos); //包含兩個狀態(tài)標(biāo)志,用"|"組合

  3. 可以看到:對輸出格式的控制,既可以用控制符(如例13.2),也可以用cout流的有關(guān)成員函數(shù)(如例13.3),二者的作用是相同的。控制符是在頭文件iomanip中定義的,因此用控制符時,必須包含iomanip頭文件。cout流的成員函數(shù)是在頭文件iostream 中定義的,因此只需包含頭文件iostream,不必包含iomanip。許多程序人員感到使用控制符方便簡單,可以在一個cout輸出語句中連續(xù)使用多種控制符。

5.文件讀寫

  • 5.1文件流類和文件流對象

    • 輸入輸出是以系統(tǒng)指定的標(biāo)準(zhǔn)設(shè)備(輸入設(shè)備為鍵盤,輸出設(shè)備為顯示器)為對象的。在實際應(yīng)用中,常以磁盤文件作為對象。即從磁盤文件讀取數(shù)據(jù),將數(shù)據(jù)輸出到磁盤文件。
  • 和文件有關(guān)系的輸入輸出類主要在fstream.h這個頭文件中被定義,在這個頭文件中主要被定義了三個類,由這三個類控制對文件的各種輸入輸出操作,他們分別是ifstream、ofstream、fstream,其中fstream類是由iostream類派生而來,他們之間的繼承關(guān)系見下圖所示:

  • 由于文件設(shè)備并不像顯示器屏幕與鍵盤那樣是標(biāo)準(zhǔn)默認(rèn)設(shè)備,所以它在fstream頭文件中是沒有像cout那樣預(yù)先定義的全局對象,所以我們必須自己定義一個該類的對象。ifstream類,它是從istream類派生的,用來支持從磁盤文件的輸入。ofstream類,它是從ostream類派生的,用來支持向磁盤文件的輸出。fstream類,它是從iostream類派生的,用來支持對磁盤文件的輸入輸出。
  • 5.2C++打開文件

所謂打開(open)文件是一種形象的說法,如同打開房門就可以進(jìn)入房間活動一樣。 打開文件是指在文件讀寫之前做必要的準(zhǔn)備工作,包括:
1)為文件流對象和指定的磁盤文件建立關(guān)聯(lián),以便使文件流流向指定的磁盤文件。
2)指定文件的工作方式,如:該文件是作為輸入文件還是輸出文件,是ASCII文件還是二進(jìn)制文件等。
以上工作可以通過兩種不同的方法實現(xiàn):

  1. 調(diào)用文件流的成員函數(shù)open。如
   ofstream outfile;  //定義ofstream類(輸出文件流類)對象outfile
   outfile.open("f1.dat",ios::out);  //使文件流與f1.dat文件建立關(guān)聯(lián)

第2行是調(diào)用輸出文件流的成員函數(shù)open打開磁盤文件f1.dat,并指定它為輸出文件, 文件流對象outfile將向磁盤文件f1.dat輸出數(shù)據(jù)。ios::out是I/O模式的一種,表示以輸出方式打開一個文件?;蛘吆唵蔚卣f,此時f1.dat是一個輸出文件,接收從內(nèi)存 輸出的數(shù)據(jù)。
磁盤文件名可以包括路徑,如"c:\new\f1.dat",如缺省路徑,則默認(rèn)為當(dāng)前目錄下的文件。

  1. 在定義文件流對象時指定參數(shù)
    在聲明文件流類時定義了帶參數(shù)的構(gòu)造函數(shù),其中包含了打開磁盤文件的功能。因此,可以在定義文件流對象時指定參數(shù),調(diào)用文件流類的構(gòu)造函數(shù)來實現(xiàn)打開文件的功能。
  • 幾點說明:
      1. 新版本的I/O類庫中不提供ios::nocreate和ios::noreplace。
      1. 每一個打開的文件都有一個文件指針,該指針的初始位置由I/O方式指定,每次讀寫都從文件指針的當(dāng)前位置開始。每讀入一個字節(jié),指針就后移一個字節(jié)。當(dāng)文件指針移到最后,就會遇到文件結(jié)束EOF(文件結(jié)束符也占一個字節(jié),其值為-1),此時流對象的成員函數(shù)eof的值為非0值(一般設(shè)為1),表示文件結(jié)束 了。
      1. 可以用“位或”運算符“|”對輸入輸出方式進(jìn)行組合,如表13.6中最后3行所示那樣。還可以舉出下面一些例子:
    ios::in | ios:: noreplace  //打開一個輸入文件,若文件存在則返回打開失敗的信息
    ios::app | ios::nocreate  //打開一個輸出文件,在文件尾接著寫數(shù)據(jù),若文件不存在,則返回打開失敗的信息
    ios::out l ios::noreplace  //打開一個新文件作為輸出文件,如果文件已存在則返回打開失敗的信息
    ios::in l ios::out I ios::binary  //打開一個二進(jìn)制文件,可讀可寫
// 但不能組合互相排斥的方式,如
// ios::nocreate l ios::noreplace。
    1. 如果打開操作失敗,open函數(shù)的返回值為0(假),如果是用調(diào)用構(gòu)造函數(shù)的方式打開文件的,則流對象的值為0??梢該?jù)此測試打開是否成功。如
    if(outfile.open("f1.bat", ios::app) ==0)
        cout <<"open error";
或
    if( !outfile.open("f1.bat", ios::app) )
        cout <<"open error";
  • 5.3C++關(guān)閉文件

    • 在對已打開的磁盤文件的讀寫操作完成后,應(yīng)關(guān)閉該文件。關(guān)閉文件用成員函數(shù)close。如:
outfile.close( );  //將輸出文件流所關(guān)聯(lián)的磁盤文件關(guān)閉
  • 所謂關(guān)閉,實際上是解除該磁盤文件與文件流的關(guān)聯(lián),原來設(shè)置的工作方式也失效,這樣,就不能再通過文件流對該文件進(jìn)行輸入或輸出。此時可以將文件流與其他磁盤文件建立關(guān)聯(lián),通過文件流對新的文件進(jìn)行輸入或輸出。如:
  outfile.open("f2.dat",ios::app|ios::nocreate);

此時文件流outfile與f2.dat建立關(guān)聯(lián),并指定了f2.dat的工作方式。

  • 5.4C++對ASCII文件的讀寫操作

  • 如果文件的每一個字節(jié)中均以ASCII代碼形式存放數(shù)據(jù),即一個字節(jié)存放一個字符,這個文件就是ASCII文件(或稱字符文件)。程序可以從ASCII文件中讀入若干個字符,也可以向它輸出一些字符。

      1. 用流插入運算符“<<”和流提取運算符“>>”輸入輸出標(biāo)準(zhǔn)類型的數(shù)據(jù)?!?lt;<”和“ >>”都巳在iostream中被重載為能用于ostream和istream類對象的標(biāo)準(zhǔn)類型的輸入輸出。由于ifstream和 ofstream分別是ostream和istream類的派生類;因此它們從ostream和istream類繼承了公用的重載函數(shù),所以在對磁盤文件的操作中,可以通過文件流對象和流插入運算符“<<”及 流提取運算符“>>”實現(xiàn)對磁盤 文件的讀寫,如同用cin、cout和<<、>>對標(biāo)準(zhǔn)設(shè)備進(jìn)行讀寫一樣。
      1. 用文件流的put、get、geiline等成員函數(shù)進(jìn)行字符的輸入輸出,用C++流成員函數(shù)put輸出單個字符、C++ get()函數(shù)讀入一個字符和C++ getline()函數(shù)讀入一行字符。
int main(){

    char* sourceFileName = "./source.txt";
    char* targetFileName = "./target.txt";
    //創(chuàng)建文件輸入流對象
    ifstream ism(sourceFileName, ios::in);
    //創(chuàng)建文件輸出流對象
    ofstream osm(targetFileName,ios::out);

    if (!ism){
        cout << "文件打開失敗!" << endl;
    }

    while (!ism.eof()){
        char buf[1024] = { 0 };
        ism.getline(buf,1024);
        cout << buf << endl;
        osm << buf << endl;
    }

    //關(guān)閉文件流對象
    ism.close();
    osm.close();

    system("pause");
    return EXIT_SUCCESS;
}
  • 5.5C++對二進(jìn)制文件的讀寫操作

    • 二進(jìn)制文件不是以ASCII代碼存放數(shù)據(jù)的,它將內(nèi)存中數(shù)據(jù)存儲形式不加轉(zhuǎn)換地傳送到磁盤文件,因此它又稱為內(nèi)存數(shù)據(jù)的映像文件。因為文件中的信息不是字符數(shù)據(jù),而是字節(jié)中的二進(jìn)制形式的信息,因此它又稱為字節(jié)文件。

    • 對二進(jìn)制文件的操作也需要先打開文件,用完后要關(guān)閉文件。在打開時要用ios::binary指定為以二進(jìn)制形式傳送和存儲。二進(jìn)制文件除了可以作為輸入文件或輸出文件外,還可以是既能輸入又能輸出的文件。這是和ASCII文件不同的地方。

    • 用成員函數(shù)read和write讀寫二進(jìn)制文件。對二進(jìn)制文件的讀寫主要用istream類的成員函數(shù)read和write來實現(xiàn)。這兩個成員函數(shù)的原型為:

    istream& read(char *buffer,int len);
    ostream& write(const char * buffer,int len);

字符指針buffer指向內(nèi)存中一段存儲空間。len是讀寫的字節(jié)數(shù)。調(diào)用的方式為:

    a. write(p1,50);
    b. read(p2,30);
  • 上面第一行中的a是輸出文件流對象,write函數(shù)將字符指針p1所給出的地址開始的50個字節(jié)的內(nèi)容不加轉(zhuǎn)換地寫到磁盤文件中。在第二行中,b是輸入文件流對象,read 函數(shù)從b所關(guān)聯(lián)的磁盤文件中,讀入30個字節(jié)(或遇EOF結(jié)束),存放在字符指針p2所指的一段空間內(nèi)。
class Person{
public:
    Person(char* name,int age){
        strcpy(this->mName, name);
        this->mAge = age;
    }
public:
    char mName[64];
    int mAge;
};

int main(){

    char* fileName = "person.txt";
    //二進(jìn)制模式讀寫文件
    //創(chuàng)建文件對象輸出流
    ofstream osm(fileName, ios::out | ios::binary);

    Person p1("John",33);
    Person p2("Edward", 34);

    //Person對象寫入文件
    osm.write((const char*)&p1,sizeof(Person));
    osm.write((const char*)&p2, sizeof(Person));

    //關(guān)閉文件輸出流
    osm.close();

    //從文件中讀取對象數(shù)組
    ifstream ism(fileName, ios::in | ios::binary);
    if (!ism){
        cout << "打開失敗!" << endl;
    }
    
    Person p3;
    Person p4;

    ism.read((char*)&p3, sizeof(Person));
    ism.read((char*)&p4, sizeof(Person));

    cout << "Name:" << p3.mName << " Age:" << p3.mAge << endl;
    cout << "Age:" << p4.mName << " Age:" << p4.mAge << endl;

    //關(guān)閉文件輸入流
    ism.close();

    system("pause");
    return EXIT_SUCCESS;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第八章 c++輸入和輸出流 8.1 流的概念和流類庫的結(jié)構(gòu) 程序的輸入指的是從輸入文件將數(shù)據(jù)傳送給程序,程序的輸出...
    CodeDove閱讀 773評論 0 3
  • I/O流的概念 程序的輸入指的是從輸入文件將數(shù)據(jù)傳送給程序,程序的輸出指的是從程序?qū)?shù)據(jù)傳送給輸出文件。 C++輸...
    青春豬頭少年_閱讀 617評論 0 0
  • c++的輸入輸出不是建立在語言上的,而是由iostream和fstream文件中定義的一組模板類實現(xiàn)的,且這個類庫...
    Tianql閱讀 3,448評論 0 1
  • 1. I/O流的概念和流類庫的結(jié)構(gòu) 程序的輸入指的是從輸入文件將數(shù)據(jù)傳送給程序,程序的輸出指的是從程序?qū)?shù)據(jù)傳送給...
    木魚_cc閱讀 672評論 0 0
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月,有人笑有人哭,有人歡樂有人憂愁,有人驚喜有人失落,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,839評論 28 54

友情鏈接更多精彩內(nèi)容