C++文件讀寫詳解(ofstream,ifstream,fstream)
這裏主要是討論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)