C++文件輸入和輸出


1.引入頭文件fstream
fstream頭文件定義了用於文件輸入的類ifstream和文件輸出的類ofstream

2.寫文件
1)創建一個ofstream對象來管理輸出流
2)將該對象與文件關聯起來
3)使用cout方式使用該對象,唯一區別是輸出將進入文件,而不是屏幕。
4)關閉到文件的連接
示例如下:

ofstream fout;
fout.open("test.txt");
fout<<"write something";
fout.close();

創建對象和關聯文件可使用構造函數合並到一步,以上代碼等價於:

ofstream fout("test.txt");
fout<<"write something";
fout.close();

3.讀文件
1)創建一個ifstream對象來管理輸入流
2)將該對象與文件關聯起來
3)使用ifstream的方法讀文件
4)關閉到文件的連接
示例如下:

ifstream fin("test.txt");
char ch;
fin>>ch;//從文件中讀取一個字符
char buf[80];
fin>>buf;//從文件中讀取一個單詞
fin.getline(buf,80);//從文件中讀取一行
string line;
getline(fin,line);//讀取一行轉換成字符串
fin.close();

4.讀寫緩沖區
fstream流管理對象在使用cout或cin方式,讀或寫時,是通過緩沖區和文件進行交互的
而不是逐字節讀取或寫入文件的。

關於close()函數,當流對象過期(如程序終止)時,到文件的連接自動關閉,
也可使用cose()顯示關閉該連接。連接關閉后,將刷新緩沖區

與文件的連接關閉后,並不會刪除流,fstream流對象和它管理的緩沖區仍然存在,
可以將流重新連接到文件。

5.一個簡單的讀寫文件示例

#include<iostream>
#include<fstream>
#include<string>
using namespace std;
const string filename="test.txt";
int main()
{
ofstream fout(filename.c_str());
if(!fout.is_open())
{
cerr<<"無法打開文件 "<<filename<<endl;
exit(0);
}
cout<<"輸入密碼:";
float secret;
cin>>secret;
fout<<secret<<endl;
fout.close();

ifstream fin(filename.c_str());
if(!fin.is_open())
{
cerr<<"無法打開文件 "<<filename<<endl;
exit(0);
}
cout<<"輸入的密碼為:\n";
char ch;
while(fin.get(ch))
cout<<ch;
fin.close();
return 0;
}

程序中is_open()函數,是用來檢查文件是否被打開
流對象的狀態包括:
一切順利,已達到文件尾,I/O操作失敗等。如果一切順利,流狀態設置為0,否則設置為1。

6.打開多個文件
1)需要同時打開多個文件,則需要為每個文件創建一個流。
2)需要依次打開一組文件,可以只打開一個流,將它依次關聯到各個文件。

如下例所示:

ifstream fin;
fin.open("test.txt");
fin.close();
fin.clear();
fin.open("test2.txt");
fin.close();

7.文件模式

常量 含義
ios_base::in 打開文件,以便讀取
ios_base::out 打開文件,以便寫入
ios_base::ate 打開文件,並移到文件尾,和ios_base::app的區別是,后者只能在文件尾寫入,前者只是將寫入指針初始化在文件尾
ios_base::app 追加到文件尾
ios_base::trunc 如果文件存在,則清空文件內容
ios_base::binary 二進制文件

 

 

 

 

 

 

 

對於ifstream open(),默認的模式為ios_base::in
對於ofstream open(),默認的模式為ios_base::out|ios_base::trunc,打開並清空文件

8.二進制模式 ios_base::binary 

文件的存儲類型有兩種,文本格式或二進制格式
文本格式便於讀取,而二進制格式更加精確,占用空間小,讀取速度快。
寫操作:

fout.write((char*)&T,sizeof T);

讀操作:

fin.read((char*)&T,sizeof T);

注意需要將類型實例地址,強制轉換為char*類型。

9.隨機存取

隨機存取是指,讀寫指針直接移動到文件的任何位置。

跳轉函數:

istream & seekg(streamoff,ios_base::seekdir);//相對地址
istream & seekg(streampos);//絕對地址

第一個方法的意思是,離seekdir參數指定文件位置,距離streamoff的位置。
其中,streamoff單位的是字節,seekdir表示文件的三個位置(頂端ios_base::beg,底端ios_base::end,當前位置ios_base::cur)

第二個方法的意思是,離文件開頭streampos的位置
streampos表示文件中的絕對位置,單位是字節

seekg()
移到文件開頭

tellg()
返回讀寫指針當前的位置

下面,我們用二進制文件模式,寫一個簡單的隨機存取示例:

#include<iostream>
#include<fstream>
#include<iomanip>
const int LIM=20;
struct planet
{
    char name[LIM];
    double population;
    double g;
};
const char *file = "planets.dat";
inline void eatline(){while(std::cin.get()!='\n') continue;}
int main()
{
    using namespace std;
    planet pl;
    cout<<fixed;

    fstream finout;
    finout.open(file,ios_base::in|ios_base::out|ios_base::binary);
    int ct = 0;
    if(finout.is_open())
    {
        finout.seekg(0);
        cout<<"contents of file "<<file<<endl;
        while(finout.read((char *)&pl,sizeof pl))
        {
            cout<<ct++<<":"<<setw(20)<<pl.name<<":"
                <<setprecision(0)<<setw(12)<<pl.population
                <<setprecision(2)<<setw(6)<<pl.g<<endl;
        }
        if(finout.eof())
            finout.clear();
        else{
            cerr<<"無法打開文件 "<<file<<endl;
            exit(0);
        }
    }
    else{
        cerr<<"無法打開文件 "<<file<<endl;
        exit(0);
    }
    cout<<"enter record number to change:";
    long rec;
    cin>>rec;
    eatline();
    if(rec<0||rec>=ct)
    {
        cerr<<"無效 index number"<<endl;
        exit(0);
    }
    streampos place = rec*sizeof pl;
    finout.seekg(place);
    if(finout.fail())
    {
        cerr<<"無法找到 index number"<<endl;
        exit(0);
    }
    finout.read((char *)&pl,sizeof pl);
    cout<<"找到的 index number"<<endl;
    cout<<rec<<":"<<setw(20)<<pl.name<<":"
                <<setprecision(0)<<setw(12)<<pl.population
                <<setprecision(2)<<setw(6)<<pl.g<<endl;
    if(finout.eof())
        finout.clear();
    cout<<"輸入name:";
    cin.get(pl.name,LIM);
    eatline();
    cout<<"population:";
    cin>>pl.population;
    cout<<"g:";
    cin>>pl.g;
    finout.seekp(place);
    finout.write((char*)&pl,sizeof pl)<<flush;
    if(finout.fail())
    {
        cerr<<"寫失敗 index number"<<endl;
        exit(0);
    }

    ct = 0;
    finout.seekg(0);
    cout<<"contents of file "<<file<<endl;
    while(finout.read((char *)&pl,sizeof pl))
    {
        cout<<ct++<<":"<<setw(20)<<pl.name<<":"
            <<setprecision(0)<<setw(12)<<pl.population
            <<setprecision(2)<<setw(6)<<pl.g<<endl;
    }
    finout.close();
    cout<<"Done.\n";
    return 0;
}

程序中,我們使用了一個特別的流管理對象fstream,
fstream繼承子iostream,而iostream繼承自istream和ostream
因此fstream繼承了兩個緩沖區,一個用於輸入,一個用於輸出
並能同步化兩個緩沖區的處理。即輸入指針和輸出指針的位置始終相同。
這樣用一個流管理對象,就可以同時進行讀和寫。

 

參考資料:《C++ Primer.Plus》 pp.768-788


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM