【C++】面向?qū)ο笾瓹++輸入和輸出流-008

第八章 c++輸入和輸出流


8.1 流的概念和流類庫(kù)的結(jié)構(gòu)


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

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

  • 對(duì)系統(tǒng)指定的標(biāo)準(zhǔn)設(shè)備的輸入和輸出。即從鍵盤輸入數(shù)據(jù)撬呢,輸出到顯示器屏幕魂拦。這種輸入輸出稱為標(biāo)準(zhǔn)的輸入輸出芯勘,簡(jiǎn)稱標(biāo)準(zhǔn)I/O。

  • 以外存磁盤文件為對(duì)象進(jìn)行輸入和輸出安疗,即從磁盤文件輸入數(shù)據(jù)荐类,數(shù)據(jù)輸出到磁盤文件玉罐。以外存文件為對(duì)象的輸入輸出稱為文件的輸入輸出厌小,簡(jiǎn)稱文件I/O讨韭。

  • 對(duì)內(nèi)存中指定的空間進(jìn)行輸入和輸出透硝。通常指定一個(gè)字符數(shù)組作為存儲(chǔ)空間(實(shí)際上可以利用該空間存儲(chǔ)任何信息)。這種輸入和輸出稱為字符串輸入輸出罪治,簡(jiǎn)稱串I/O。

    C++編譯系統(tǒng)提供了用于輸入輸出的iostream類庫(kù)晒骇。iostream這個(gè)單詞是由3個(gè)部 分組成的洪囤,即i-o-stream,意為輸入輸出流款咖。在iostream類庫(kù)中包含許多用于輸入輸出的 類海洼。常用的見(jiàn)表

    在這里插入圖片描述

在這里插入圖片描述

ios是抽象基類域帐,由它派生出istream類和ostream類民假,兩個(gè)類名中第1個(gè)字母io分別代表輸入(input)和輸出(output)羊异。 istream類支持輸入操作,ostream類支持輸出操作平道, iostream類支持輸入輸出操作。iostream類是從istream類和ostream類通過(guò)多重繼承而派生的類陆淀。其繼承層次見(jiàn)上圖表示。

C++對(duì)文件的輸入輸出需要用ifstrcamofstream類含懊,兩個(gè)類名中第1個(gè)字母io分別代表輸入和輸出岔乔,第2個(gè)字母f代表文件 (file)。ifstream支持對(duì)文件的輸入操作茁影, ofstream支持對(duì)文件的輸出操作。類ifstream繼承了類istream浩螺,類ofstream繼承了類ostream靴患,類fstream繼承了 類iostream。見(jiàn)圖

在這里插入圖片描述

I/O類庫(kù)中還有其他一些類要出,但是對(duì)于一般用戶來(lái)說(shuō)鸳君,以上這些已能滿足需要了。

1.與iostream類庫(kù)有關(guān)的頭文件

iostream類庫(kù)中不同的類的聲明被放在不同的頭文件中患蹂,用戶在自己的程序中用#include命令包含了有關(guān)的頭文件就相當(dāng)于在本程序中聲明了所需 要用到的類或颊「窳耍可以換 —種說(shuō)法:頭文件是程序與類庫(kù)的接口悄但,iostream類庫(kù)的接口分別由不同的頭文件來(lái)實(shí)現(xiàn)嚎京。常用的有

  • iostream 包含了對(duì)輸入輸出流進(jìn)行操作所需的基本信息帕涌。
  • fstream 用于用戶管理的文件的I/O操作辟躏。
  • strstream 用于字符串流I/O末秃。
  • stdiostream 用于混合使用C和C + +的I/O機(jī)制時(shí)铃将,例如想將C程序轉(zhuǎn)變?yōu)镃++程序悯仙。
  • iomanip 在使用格式化I/O時(shí)應(yīng)包含此頭文件。

2.在iostream頭文件中定義的流對(duì)象

iostream 頭文件中定義的類有 ios千贯,istreamostreamiostreamistream 等。
iostream頭文件中不僅定義了有關(guān)的類浩淘,還定義了4種流對(duì)象左驾,

對(duì)象 含義 對(duì)應(yīng)設(shè)備 對(duì)應(yīng)的類 c語(yǔ)言中相應(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)錯(cuò)誤流 屏幕 ostream_withassign stderr
clog 標(biāo)準(zhǔn)錯(cuò)誤流 屏幕 ostream_withassign stderr

在iostream頭文件中定義以上4個(gè)流對(duì)象用以下的形式(以cout為例):

ostream cout ( stdout);

在定義coutostream流類對(duì)象時(shí)桅锄,把標(biāo)準(zhǔn)輸出設(shè)備stdout作為參數(shù),這樣它就與標(biāo)準(zhǔn)輸出設(shè)備(顯示器)聯(lián)系起來(lái)甥桂,如果有

 cout <<3;

就會(huì)在顯示器的屏幕上輸出3律歼。

3.在iostream頭文件中重載運(yùn)算符

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

#include <iostream>

1).>>a表示將數(shù)據(jù)放入a對(duì)象中。
2). <<a表示將a對(duì)象中存儲(chǔ)的數(shù)據(jù)拿出姐赡。

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


標(biāo)準(zhǔn)I/O對(duì)象:cin州疾,cout毒姨,cerr崩哩,clog

1.cout流對(duì)象

cout是console output的縮寫(xiě)棚贾,意為在控制臺(tái)(終端顯示器)的輸出。強(qiáng)調(diào)幾點(diǎn)媚送。

  1. cout不是C++預(yù)定義的關(guān)鍵字,它是ostream流類的對(duì)象杀怠,在iostream中定義。 顧 名思義,流是流動(dòng)的數(shù)據(jù)仰禽,cout流是流向顯示器的數(shù)據(jù)凤藏。cout流中的數(shù)據(jù)是用流插入 運(yùn)算符“<<”順序加入的。如果有:
    cout<<"I "<<"study C++ "<<"very hard. << “hello world !";
    按順序?qū)⒆址?I ", "study C++ ", "very hard."插人到cout流中,cout就將它們送 到顯示器擂煞,在顯示器上輸出字符串"I study C++ very hard."哀托。cout流是容納數(shù)據(jù)的載 體玻淑,它并不是一個(gè)運(yùn)算符贬蛙。人們關(guān)心的是cout流中的內(nèi)容,也就是向顯示器輸出什么规婆。

  2. 用“cout<<”輸出基本類型的數(shù)據(jù)時(shí)浊伙,可以不必考慮數(shù)據(jù)是什么類型赵抢,系統(tǒng)會(huì)判斷數(shù) 據(jù)的類型,并根據(jù)其類型選擇調(diào)用與之匹配的運(yùn)算符重 載函數(shù)绰姻。這個(gè)過(guò)程都是自動(dòng)的锯蛀, 用戶不必干預(yù)掠械。如果在C語(yǔ)言中用prinf函數(shù)輸出不同類型的數(shù)據(jù)层扶,必須分別指定相應(yīng) 的輸出格式符亩码,十分麻煩汹买,而且容易出錯(cuò)盐股。C++的I/O機(jī)制對(duì)用戶來(lái)說(shuō),顯然是方便 而安全的。

  3. cout流在內(nèi)存中對(duì)應(yīng)開(kāi)辟了一個(gè)緩沖區(qū),用來(lái)存放流中的數(shù)據(jù),當(dāng)向cout流插人一個(gè)endl時(shí)馋辈,不論緩沖區(qū)是否已滿耘拇,都立即輸出流中所有數(shù)據(jù)帆喇,然后插入一個(gè)換行符洋丐, 并刷新流(清空緩沖區(qū))卜范。注意如果插人一個(gè)換行符”\n“(如cout<<a<<"\n")嗡害,則只輸出和換行良价,而不刷新cout 流(但并不是所有編譯系統(tǒng)都體現(xiàn)出這一區(qū)別)熔酷。

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

2.cerr流對(duì)象

cerr流對(duì)象是標(biāo)準(zhǔn)錯(cuò)誤流,cerr流已被指定為與顯示器關(guān)聯(lián)蓖康。
cerr的 作用是向標(biāo)準(zhǔn)錯(cuò)誤設(shè)備(standard error device)輸出有關(guān)出錯(cuò)信息熟菲。cerr與標(biāo)準(zhǔn)輸出流cout的作用和用法差不多。

但有一點(diǎn)不同:cout流通常是傳送到顯示器輸出,但也可以被重定向輸出到磁盤文件,而cerr流中的信息只能在顯示器輸出煎娇。當(dāng)調(diào)試程序時(shí)痰憎,往往不希望程序運(yùn)行時(shí)的出錯(cuò)信息被送到其他文件,而要求在顯示器上及時(shí)輸出密强,這時(shí) 應(yīng)該用cerr端考。cerr流中的信息是用戶根據(jù)需要指定的雅潭。

3.clog流對(duì)象

clog流對(duì)象也是標(biāo)準(zhǔn)錯(cuò)誤流,它是console log的縮寫(xiě)却特。它的作用和cerr相同扶供,都是在終端顯示器上顯示出錯(cuò)信息。
區(qū)別cerr是不經(jīng)過(guò)緩沖區(qū)裂明,直接向顯示器上輸出有關(guān)信息椿浓,而clog中的信息存放在緩沖區(qū)中,緩沖區(qū)滿后或遇endl時(shí)向顯示器輸出漾岳。

緩沖區(qū)的概念:

在這里插入圖片描述

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


標(biāo)準(zhǔn)輸入流對(duì)象cin轰绵,重點(diǎn)掌握的函數(shù)

cin.get() //一次只能讀取一個(gè)字符
cin.get(一個(gè)參數(shù)) //讀一個(gè)字符
cin.get(兩個(gè)參數(shù)) //可以讀字符串
cin.getline()
cin.ignore()
cin.peek()
cin.putback()
//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ū)取走一個(gè)字符
    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 << "請(qǐng)輸入一個(gè)數(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;
    }
}

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


8.4.1 字符輸出

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

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

//cout.write 輸出字符串 buf,輸出多少個(gè)
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;
    }

}

8.4.2 格式化輸出

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

1.使用控制符的方法麸祷;
2.使用流對(duì)象的有關(guān)成員函數(shù)澎怒。

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

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

在這里插入圖片描述

流成員函數(shù)setf和控制符setiosflags括號(hào)中的參數(shù)表示格式狀態(tài)阶牍,它是通過(guò)格式標(biāo)志來(lái)指定的喷面。格式標(biāo)志在類ios中被定義為枚舉值星瘾。因此在引用這些格式標(biāo)志時(shí)要在前面加上類名ios和域運(yùn)算符“::”。格式標(biāo)志見(jiàn)表13.5惧辈。
在這里插入圖片描述

8.4.2.2 控制符格式化輸出

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

在這里插入圖片描述
//通過(guò)流成員函數(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;

}

8.4.2.3 對(duì)程序的幾點(diǎn)說(shuō)明

  1. 成員函數(shù)width(n)和控制符setw(n)只對(duì)其后的第一個(gè)輸出項(xiàng)有效浴栽。如:
    cout. width(6);
    cout <<20 <<3.14<<endl;

    輸出結(jié)果為 203.14
    在輸出第一個(gè)輸出項(xiàng)20時(shí)煤痕,域?qū)挒?,因此在20前面有4個(gè)空格碗脊,在輸出3.14時(shí)边翁,width (6)已不起作用翎承,此時(shí)按系統(tǒng)默認(rèn)的域?qū)捿敵觯ò磾?shù)據(jù)實(shí)際長(zhǎng)度輸出)。如果要求在輸出數(shù)據(jù)時(shí)都按指定的同一域?qū)抧輸出符匾,不能只調(diào)用一次width(n)审洞, 而必須在輸出每一項(xiàng)前都調(diào)用一次width(n),上面的程序中就是這樣做的待讳。

  2. 在表13.5中的輸出格式狀態(tài)分為5組,每一組中同時(shí)只能選用一種(例如dec仰剿、hex和oct中只能選一创淡,它們是互相排斥的)。在用成員函數(shù)setf和 控制符setiosflags設(shè)置輸出格式狀態(tài)后南吮,如果想改設(shè)置為同組的另一狀態(tài)琳彩,應(yīng)當(dāng)調(diào)用成員函數(shù)unsetf(對(duì)應(yīng)于成員函數(shù)self)或 resetiosflags(對(duì)應(yīng)于控制符setiosflags),先終止原來(lái)設(shè)置的狀態(tài)部凑。然后再設(shè)置其他狀態(tài)露乏,大家可以從本程序中看到這點(diǎn)。程序在開(kāi) 始雖然沒(méi)有用成員函數(shù)self和控制符setiosflags設(shè)置用dec輸出格式狀態(tài)涂邀,但系統(tǒng)默認(rèn)指定為dec瘟仿,因此要改變?yōu)?code>hex或oct,也應(yīng)當(dāng)先 用unsetf 函數(shù)終止原來(lái)設(shè)置比勉。如果刪去程序中的第7行和第10行劳较,雖然在第8行和第11行中用成員函數(shù)setf設(shè)置了hexoct格式,由于未終止dec格式浩聋,因 此hexoct的設(shè)置均不起作用观蜗,系統(tǒng)依然以十進(jìn)制形式輸出。
    同理衣洁,程序倒數(shù)第8行的unsetf 函數(shù)的調(diào)用也是不可缺少的墓捻。

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

  4. 可以看到:對(duì)輸出格式的控制,既可以用控制符(如例13.2)袱院,也可以用cout流的有關(guān)成員函數(shù)(如例13.3)屎慢,二者的作用是相同的『雎澹控制符是在頭文件iomanip中定義的腻惠,因此用控制符時(shí),必須包含iomanip頭文件欲虚。cout流的成員函數(shù)是在頭文件iostream 中定義的集灌,因此只需包含頭文件iostream,不必包含iomanip复哆。許多程序人員感到使用控制符方便簡(jiǎn)單欣喧,可以在一個(gè)cout輸出語(yǔ)句中連續(xù)使用多種控制符。

8.4 文件讀寫(xiě)


8.4.1文件流類和文件流對(duì)象

輸入輸出是以系統(tǒng)指定的標(biāo)準(zhǔn)設(shè)備(輸入設(shè)備為鍵盤梯找,輸出設(shè)備為顯示器)為對(duì)象的唆阿。在實(shí)際應(yīng)用中,常以磁盤文件作為對(duì)象锈锤。即從磁盤文件讀取數(shù)據(jù)驯鳖,將數(shù)據(jù)輸出到磁盤文件。和文件有關(guān)系的輸入輸出類主要在fstream.h這個(gè)頭文件中被定義久免,在這個(gè)頭文件中主要被定義了三個(gè)類浅辙,由這三個(gè)類控制對(duì)文件的各種輸入輸出操作,他們分別是ifstream阎姥、ofstream记舆、fstream,其中fstream類是由iostream類派生而來(lái)呼巴,他們之間的繼承關(guān)系見(jiàn)下圖所示:

在這里插入圖片描述

由于文件設(shè)備并不像顯示器屏幕與鍵盤那樣是標(biāo)準(zhǔn)默認(rèn)設(shè)備氨淌,所以它在fstream頭文件中是沒(méi)有像cout那樣預(yù)先定義的全局對(duì)象,所以我們必須自己定義一個(gè)該類的對(duì)象伊磺。ifstream類盛正,它是從istream類派生的,用來(lái)支持從磁盤文件的輸入屑埋。ofstream類豪筝,它是從ostream類派生的,用來(lái)支持向磁盤文件的輸出。

fstream類续崖,它是從iostream類派生的敲街,用來(lái)支持對(duì)磁盤文件的輸入輸出。

8.4.2 C++打開(kāi)文件

所謂打開(kāi)(open)文件是一種形象的說(shuō)法严望,如同打開(kāi)房門就可以進(jìn)入房間活動(dòng)一樣多艇。 打開(kāi)文件是指在文件讀寫(xiě)之前做必要的準(zhǔn)備工作,包括:

  1. 為文件流對(duì)象和指定的磁盤文件建立關(guān)聯(lián)像吻,以便使文件流流向指定的磁盤文件峻黍。
  2. 指定文件的工作方式,如:該文件是作為輸入文件還是輸出文件拨匆,是ASCII文件還是二進(jìn)制文件等姆涩。

以上工作可以通過(guò)兩種不同的方法實(shí)現(xiàn):

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

第2行是調(diào)用輸出文件流的成員函數(shù)open打開(kāi)磁盤文件f1.dat惭每,并指定它為輸出文件骨饿,文件流對(duì)象outfile將向磁盤文件f1.dat輸出數(shù)據(jù)。ios::out是I/O模式的一種台腥,表示 以輸出方式打開(kāi)一個(gè)文件宏赘。或者簡(jiǎn)單地說(shuō)黎侈,此時(shí)f1.dat是一個(gè)輸出文件置鼻,接收從內(nèi)存 輸出的數(shù)據(jù)。
磁盤文件名可以包括路徑蜓竹,如"c:\\new\\f1.dat",如缺省路徑储藐,則默認(rèn)為當(dāng)前目錄下的文件俱济。

  1. 在定義文件流對(duì)象時(shí)指定參數(shù)
    在聲明文件流類時(shí)定義了帶參數(shù)的構(gòu)造函數(shù),其中包含了打開(kāi)磁盤文件的功能钙勃。因此蛛碌, 可以在定義文件流對(duì)象時(shí)指定參數(shù),調(diào)用文件流類的構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)打開(kāi)文件的功能辖源。


    在這里插入圖片描述

幾點(diǎn)說(shuō)明:

  1. 新版本的I/O類庫(kù)中不提供ios::nocreateios::noreplace蔚携。

  2. 每一個(gè)打開(kāi)的文件都有一個(gè)文件指針,該指針的初始位置由I/O方式指定克饶,每次讀寫(xiě)都從文件指針的當(dāng)前位置開(kāi)始酝蜒。每讀入一個(gè)字節(jié),指針就后移一個(gè)字節(jié)矾湃。當(dāng)文件指針移到最后亡脑,就會(huì)遇到文件結(jié)束EOF(文件結(jié)束符也占一個(gè)字節(jié),其值為-1),此時(shí)流對(duì)象的成員函數(shù)eof的值為非0值(一般設(shè)為1)霉咨,表示文件結(jié)束 了蛙紫。

  3. 可以用“位或”運(yùn)算符“|”對(duì)輸入輸出方式進(jìn)行組合,如表13.6中最后3行所示那樣途戒。還可以舉出下面一些例子:

    ios::in | ios:: noreplace  //打開(kāi)一個(gè)輸入文件坑傅,若文件不存在則返回打開(kāi)失敗的信息
    ios::app | ios::nocreate  //打開(kāi)一個(gè)輸出文件,在文件尾接著寫(xiě)數(shù)據(jù)喷斋,若文件不存在唁毒,則返回打開(kāi)失敗的信息
    ios::out l ios::noreplace  //打開(kāi)一個(gè)新文件作為輸出文件,如果文件已存在則返回打開(kāi)失敗的信息
    ios::in l ios::out I ios::binary  //打開(kāi)一個(gè)二進(jìn)制文件继准,可讀可寫(xiě)

但不能組合互相排斥的方式枉证,如 ios::nocreate l ios::noreplace

  1. 如果打開(kāi)操作失敗移必,open函數(shù)的返回值為0(假)室谚,如果是用調(diào)用構(gòu)造函數(shù)的方式打開(kāi)文件的,則流對(duì)象的值為0崔泵∶氤啵可以據(jù)此測(cè)試打開(kāi)是否成功。如
    if(outfile.open("f1.bat", ios::app) ==0)
        cout <<"open error";
或
    if( !outfile.open("f1.bat", ios::app) )
        cout <<"open error";

8.4.3 C++關(guān)閉文件

在對(duì)已打開(kāi)的磁盤文件的讀寫(xiě)操作完成后憎瘸,應(yīng)關(guān)閉該文件入篮。關(guān)閉文件用成員函數(shù)close

如:outfile.close( );  //將輸出文件流所關(guān)聯(lián)的磁盤文件關(guān)閉

所謂關(guān)閉幌甘,實(shí)際上是解除該磁盤文件與文件流的關(guān)聯(lián)潮售,原來(lái)設(shè)置的工作方式也失效,這樣锅风,就不能再通過(guò)文件流對(duì)該文件進(jìn)行輸入或輸出酥诽。 此時(shí)可以將文件流與其他磁盤文件建立關(guān)聯(lián),通過(guò)文件流對(duì)新的文件進(jìn)行輸入或輸出皱埠。如:

    outfile.open("f2.dat",ios::app|ios::nocreate)肮帐;
   此時(shí)文件流outfile與f2.dat建立關(guān)聯(lián),并指定了f2.dat的工作方式边器。

8.4.4 C++對(duì)ASCII文件的讀寫(xiě)操作

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

  1. 用流插入運(yùn)算符“<<”和流提取運(yùn)算符“>>”輸入輸出標(biāo)準(zhǔn)類型的數(shù)據(jù)忘巧『憬纾“<<”和“ >>”都巳在iostream中被重載為能用于ostreamistream類對(duì)象的標(biāo)準(zhǔn)類型的輸入輸出。由于ifstreamofstream分別是ostreamistream類的派生類砚嘴;因此它們從ostreamistream類繼承了公用的重載函數(shù)仗处,所以在對(duì)磁盤文件的操作中眯勾,可以通過(guò)文件流對(duì)象和流插入運(yùn)算符“<<”及 流提取運(yùn)算符“>>”實(shí)現(xiàn)對(duì)磁盤 文件的讀寫(xiě),如同用cin婆誓、cout<<吃环、>>對(duì)標(biāo)準(zhǔn)設(shè)備進(jìn)行讀寫(xiě)一樣。

  2. 用文件流的put洋幻、get郁轻、geiline等成員函數(shù)進(jìn)行字符的輸入輸出,:用C++流成員函數(shù)put輸出單個(gè)字符文留、C++ get()函數(shù)讀入一個(gè)字符和C++ getline()函數(shù)讀入一行字符好唯。

int main(){

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

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

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

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

    system("pause");
    return EXIT_SUCCESS;
}

8.4.5 C++對(duì)二進(jìn)制文件的讀寫(xiě)操作

二進(jìn)制文件不是以ASCII代碼存放數(shù)據(jù)的,它將內(nèi)存中數(shù)據(jù)存儲(chǔ)形式不加轉(zhuǎn)換地傳送到磁盤文件燥翅,因此它又稱為內(nèi)存數(shù)據(jù)的映像文件骑篙。因?yàn)槲募械男畔⒉皇亲址麛?shù)據(jù),而是字節(jié)中的二進(jìn)制形式的信息森书,因此它又稱為字節(jié)文件靶端。

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

用成員函數(shù)read和write讀寫(xiě)二進(jìn)制文件

對(duì)二進(jìn)制文件的讀寫(xiě)主要用istream類的成員函數(shù)readwrite來(lái)實(shí)現(xiàn)台谍。這兩個(gè)成員函數(shù)的原型為

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

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

    a. write(p1,50);
    b. read(p2,30);

上面第一行中的a是輸出文件流對(duì)象趁蕊,write函數(shù)將字符指針p1所給出的地址開(kāi)始的50個(gè)字節(jié)的內(nèi)容不加轉(zhuǎn)換地寫(xiě)到磁盤文件中。在第二行中仔役,b是輸入文件流對(duì)象掷伙,read 函數(shù)從b所關(guān)聯(lián)的磁盤文件中,讀入30個(gè)字節(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)制模式讀寫(xiě)文件
    //創(chuàng)建文件對(duì)象輸出流
    ofstream osm(fileName, ios::out | ios::binary);

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

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

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

    //從文件中讀取對(duì)象數(shù)組
    ifstream ism(fileName, ios::in | ios::binary);
    if (!ism){
        cout << "打開(kāi)失敗!" << 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)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末赃泡,一起剝皮案震驚了整個(gè)濱河市寒波,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌升熊,老刑警劉巖俄烁,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異级野,居然都是意外死亡页屠,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)辰企,“玉大人风纠,你說(shuō)我怎么就攤上這事±蚊常” “怎么了竹观?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)潜索。 經(jīng)常有香客問(wèn)我臭增,道長(zhǎng),這世上最難降的妖魔是什么竹习? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任誊抛,我火速辦了婚禮,結(jié)果婚禮上整陌,老公的妹妹穿的比我還像新娘拗窃。我一直安慰自己,他們只是感情好蔓榄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布并炮。 她就那樣靜靜地躺著,像睡著了一般甥郑。 火紅的嫁衣襯著肌膚如雪逃魄。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天澜搅,我揣著相機(jī)與錄音伍俘,去河邊找鬼。 笑死勉躺,一個(gè)胖子當(dāng)著我的面吹牛癌瘾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播饵溅,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼妨退,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蜕企?” 一聲冷哼從身側(cè)響起咬荷,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎轻掩,沒(méi)想到半個(gè)月后幸乒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡唇牧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年罕扎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了聚唐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡腔召,死狀恐怖杆查,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宴咧,我是刑警寧澤根灯,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站掺栅,受9級(jí)特大地震影響烙肺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜氧卧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一桃笙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沙绝,春花似錦搏明、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至粗悯,卻和暖如春虚循,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背样傍。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工横缔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人衫哥。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓茎刚,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親撤逢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子膛锭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1. I/O流的概念和流類庫(kù)的結(jié)構(gòu) 程序的輸入指的是從輸入文件將數(shù)據(jù)傳送給程序初狰,程序的輸出指的是從程序?qū)?shù)據(jù)傳送給...
    木魚(yú)_cc閱讀 591評(píng)論 0 0
  • //出自51博客:www.Amanda0928.51.com 第一章 一、選擇題 1.B; (typedef ,t...
    Damongggggg閱讀 11,130評(píng)論 0 1
  • 淺談C++常用輸入輸出 在編寫(xiě)C++程序的時(shí)候妇押,經(jīng)常因?yàn)檩斎胼敵鲱^疼跷究,所以在這里做一個(gè)小結(jié)姓迅,記錄一下常用的輸入輸出...
    MinoyJet閱讀 3,749評(píng)論 0 6
  • C/C++輸入輸出流總結(jié) 前兩天寫(xiě)C++實(shí)習(xí)作業(yè)敲霍,突然發(fā)現(xiàn)I/O是那么的陌生俊马,打了好長(zhǎng)時(shí)間的文件都沒(méi)有打開(kāi),今天終...
    LuckTime閱讀 1,732評(píng)論 0 6
  • To be a cheer up person. Cheer up for the others and myself!
    lychen2018閱讀 296評(píng)論 0 0