這里主要是討論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
*/
