1. 程式人生 > >C++文件讀寫詳解(ofstream,ifstream,fstream)

C++文件讀寫詳解(ofstream,ifstream,fstream)

for ase try and line 創建 als pac 控制臺

技術分享圖片

這裏主要是討論fstream的內容:

1 #include <fstream>  
2 ofstream         //文件寫操作 內存寫入存儲設備   
3 ifstream         //文件讀操作,存儲設備讀區到內存中  
4 fstream          //讀寫操作,對打開的文件可進行讀寫操作

1、打開文件

在fstream類中,成員函數open()實現打開文件的操作,從而將數據流和文件進行關聯,通過ofstream,ifstream,fstream對象進行對文件的讀寫操作

函數:open()

 1 public member function  
 2   
 3 void open ( const char * filename,  
 4             ios_base::openmode mode = ios_base::in | ios_base::out );  
 5   
 6 void open(const wchar_t *_Filename,  
 7         ios_base::openmode mode= ios_base::in | ios_base::out,  
 8         int prot = ios_base::_Openprot);
 9 /*
10 參數:filename   操作文件名
11            mode        打開文件的方式
12            prot         打開文件的屬性    //基本很少用到,在查看資料時,發現有兩種方式
13 
14 */

打開文件的方式在IOS類(流式I/O的基類)中定義,有如下幾種方式:

ios::in
為輸入(讀)而打開文件,文件不存在則創建(ifstream)默認的打開方式

ios::out

為輸出(寫)而打開文件,文件不存在則創建,若文件已存在則清空原內容

(ofstream默認的打開方式)

ios::ate 
文件打開時,指針在文件最後。可改變指針的位置,常和in、out聯合使用

ios::app

供寫使用,文件不存在則創建,若文件已存在則在原文件內容後寫入新的內容,

指針位置總在最後

ios::trunc
在讀寫前,先將文件長度截斷為0(默認)

ios::nocreate
文件不存在時產生錯誤,常和in或app聯合使用

ios::noreplace
文件存在時產生錯誤,常和out聯合使用

ios::binary
二進制格式文件

這些方式是能夠以“或”運算(“|”)的方式進行組合使用。

文件保護方式選擇項

filebuf::openprot
默認的兼容共享方式

filebuf::sh_none
獨占,不共享

filebuf::sh_read
讀共享

filebuf::sh_write
寫共享

很多程序中,可能會碰到ofstream out("Hello.txt"), ifstream in("..."),fstream foi("...")這樣的的使用,並沒有顯式的去調用open()函數就進行文件的操作,直接調用了其默認的打開方式,因為在stream類的構造函數中調用了open()函數,並擁有同樣的構造函數,所以在這裏可以直接使用流對象進行文件的操作,默認方式如下:

1 ofstream out("...", ios::out);  
2 ifstream in("...", ios::in);  
3 fstream foi("...", ios::in|ios::out);  

2.關閉文件

當文件讀寫操作完成之後,我們必須將文件關閉以使文件重新變為可訪問的。成員函數close(),它負責將緩存中的數據排放出來並關閉文件,這個函數一旦被調用,原先的流對象就可以被用來打開其它的文件,這個文件也就可以重新被其它的進程所訪問。為防止流對象被銷毀時還聯系著打開的文件,析構函數將會自動調用關閉函數close。

3.文本文件的讀寫

類ofstream, ifstream 和fstream 是分別從ostream, istream 和iostream 中引申而來的。這就是為什麽 fstream 的對象可以使用其父類的成員來訪問數據。一般來說,我們將使用這些類與同控制臺(console)交互同樣的成員函數(cin 和 cout)來進行輸入輸出。如下面的程序所示,我們使用重載的插入操作符<<和讀出操作符>>:

 1 #include "iostream"
 2 #include<fstream>
 3 using namespace std;
 4 void main()
 5 {
 6     fstream f("d:\\try.txt", ios::out);//供寫使用,文件不存在則創建,存在則清空原內容
 7     f << 1234 << ‘ ‘ << 3.14 << ‘A‘ << "How are you"; //寫入數據
 8     f.close();//關閉文件以使其重新變為可訪問,函數一旦調用,原先的流對象就可以被用來打開其它的文件
 9     f.open("d:\\try.txt", ios::in);//打開文件,供讀
10     int i;
11     double d;
12     char c;
13     char s[20];
14     f >> i >> d >> c;               //讀取數據
15     f.getline(s, 20);
16     cout << i << endl;             //顯示各數據
17     cout << d << endl;
18     cout << c << endl;
19     cout << s << endl;
20     f.close();
21 }
狀態標誌符的驗證(Verification of state flags)
  • bad()

    如果在讀寫過程中出錯,返回 true 。例如:當我們要對一個不是打開為寫狀態的文件進行寫入時,或者我們要寫入的設備沒有剩余空間的時候。

  • fail()

    除了與bad() 同樣的情況下會返回 true 以外,加上格式錯誤時也返回true ,例如當想要讀入一個整數,而獲得了一個字母的時候。

  • eof()

    如果讀文件到達文件末尾,返回true。

  • good()

    這是最通用的:如果調用以上任何一個函數返回true 的話,此函數返回 false 。

要想重置以上成員函數所檢查的狀態標誌,你可以使用成員函數clear(),沒有參數。

獲得和設置流指針(get and put stream pointers)

  所有輸入/輸出流對象(i/o streams objects)都有至少一個流指針:

  • ifstream, 類似istream, 有一個被稱為get pointer的指針,指向下一個將被讀取的元素。
  • ofstream, 類似 ostream, 有一個指針 put pointer ,指向寫入下一個元素的位置。
  • fstream, 類似 iostream, 同時繼承了get 和 put
  • tellg() 和 tellp()

 這兩個成員函數不用傳入參數,返回pos_type 類型的值(根據ANSI-C++ 標準) ,就是一個整數,代表當前讀出流get指針的位置 (用tellg) 或寫入流put指針的位置(用tellp)。

  • seekg() 和seekp()

  這對函數分別用來改變流指針get 和put的位置。兩個函數都被重載為兩種不同的原型:

(一)

1 seekg ( pos_type position );
2 seekp ( pos_type position );
3 /*
4 使用這個原型,流指針被改變為指向從文件開始計算的一個絕對位置。要求傳入的參數類型與函數 tellg 和tellp 的返回值類型相同。
5 */

(二)

1 seekg ( off_type offset, seekdir direction );
2 seekp ( off_type offset, seekdir direction );
3 /*
4 該原型有兩個參數:第一個參數是偏移量,
5 第二個參數是基地址。它可以是: 6 ios::beg 從流開始位置計算的位移 7 ios::cur 從流指針當前位置開始計算的位移 8 ios::end 從流末尾處開始計算的位移 9 */

流指針 get 和 put 的值對文本文件(text file)和二進制文件(binary file)的計算方法都是不同的,因為文本模式的文件中某些特殊字符可能被修改。由於這個原因,建議對以文本文件模式打開的文件總是使用seekg 和 seekp的第一種原型,而且不要對tellg 或 tellp 的返回值進行修改。對二進制文件,你可以任意使用這些函數,應該不會有任何意外的行為產生。

以下程序使用這些函數來獲得一個二進制文件的大小:

// obtaining file size  
   #include <iostream>  
   #include <fstream>  
   using namespace std;
   const char * filename = "test.txt";  
     
   int main () {  
       long l,m;  
       ifstream in(filename, ios::in|ios::binary);  
       l = in.tellg();  //當前get流指針的位置
       in.seekg (0, ios::end); //基地址為文件結束處,偏移地址為0,於是指針定位在文件結束處
       m = in.tellg();  //再次獲取當前get流指針的位置
       in.close();  
       cout << "size of " << filename;  
       cout << " is " << (m-l) << " bytes.\n";  
       return 0;  
   }  
    
  //結果:  
  size of example.txt is 2422 bytes.  

4.二進制文件

 在二進制文件中,使用<< 和>>,以及函數(如getline)來操作符輸入和輸出數據,沒有什麽實際意義,雖然它們是符合語法的。

  文件流包括兩個為順序讀寫數據特殊設計的成員函數:write 和 read。第一個函數 (write) 是ostream 的一個成員函數,都是被ofstream所繼承。而read 是istream 的一個成員函數,被ifstream 所繼承。類 fstream 的對象同時擁有這兩個函數。它們的原型是:

1 write ( char * buffer, streamsize size ); 2 read ( char * buffer, streamsize size );

這裏 buffer 是一塊內存的地址,用來存儲或讀出數據。參數size 是一個整數值,表示要從緩存(buffer)中讀出或寫入的字符數。

 1 // reading binary file  
 2 #include <iostream>  
 3 #include <fstream>  
 4 using namespace std;
 5 
 6 const char * filename = "test.txt";
 7 
 8 int main() {
 9     char * buffer;
10     long size;
11     ifstream in(filename, ios::in | ios::binary | ios::ate);
12     size = in.tellg();
13     in.seekg(0, ios::beg);
14     buffer = new char[size];
15     in.read(buffer, size);
16     in.close();
17     for (int i = 0; i < size; i++)
18     {
19         if (buffer[i] != ‘\0‘)
20             cout << buffer[i];
21     }
22     cout << endl;
23     delete[] buffer;
24     return 0;
25 }
26 /*
27 運行結果:
28 This is test!
29 My name is Mengmeng
30 */

5.逐行讀取寫入txt文件

寫入:

 1 #include <iostream>
 2 #include <fstream>
 3 using namespace std;
 4 void main()
 5 {
 6     ofstream in;
 7 in.open("com.txt",ios::trunc); //ios::trunc表示在打開文件前將文件清空,由於是寫入,文件不存在則創建
 8 int i;
 9 char a=‘a‘;
10 for(i=1;i<=26;i++)//將26個數字及英文字母寫入文件
11 {
12    if(i<10)
13    {
14     in<<"0"<<i<<"\t"<<a<<"\n";
15     a++;
16    }
17    else
18    {
19     in<<i<<"\t"<<a<<"\n";
20     a++;
21    }
22 }
23 in.close();//關閉文件
24 }
25 
26 /*
27 運行結果:
28 01    a
29 02    b
30 03    c
31 04    d
32 05    e
33 06    f
34 07    g
35 08    h
36 09    i
37 10    j
38 11    k
39 12    l
40 13    m
41 14    n
42 15    o
43 16    p
44 17    q
45 18    r
46 19    s
47 20    t
48 21    u
49 22    v
50 23    w
51 24    x
52 25    y
53 26    z
54 */

讀出:

//第一種方法:
#include<fstream>
#include<string>
#include<iostream>
using namespace std;
void main()
{
    ifstream in("com.txt");
    string s;
    while (getline(in, s))//逐行讀取數據並存於s中,直至數據全部讀取
        cout << s.c_str() << endl;
}

/*
getline函數是頭文件string中定義的函數,包含兩個參數:一是文件流的對象,二是獲取後存放的變量
*/

//第二種方法:
#include <iostream>
#include <fstream>
using namespace std;
void main()
{
    char buffer[256];
    fstream out;
    out.open("com.txt", ios::in| ios::binary);
    cout << "com.txt" << " 的內容如下:" << endl;
    while (!out.eof())
    {
        out.getline(buffer, 256, ‘\n‘);//getline(char *,int,char) 表示該行字符達到256個或遇到換行就結束
        cout << buffer << endl;
    }
    out.close();
}

/*
getline函數是istream頭文件中定義的函數,它包含三個參數:一是存放的指針名稱;
二是size,表明每行的最大長度,表明當該行字符達到最大長度時結束
三是結束的標誌,即讀取每一行時,遇到哪個標誌結束,而該標誌後面的內容當作下一行來讀取。
*/
/*
運行結果:
com.txt的內容如下:
01    a
02    b
03    c
04    d
05    e
06    f
07    g
08    h
09    i
10    j
11    k
12    l
13    m
14    n
15    o
16    p
17    q
18    r
19    s
20    t
21    u
22    v
23    w
24    x
25    y
26    z
*/

轉自:https://www.cnblogs.com/codingmengmeng/p/5545042.html

C++文件讀寫詳解(ofstream,ifstream,fstream)