C++文件操作

文件操作必須包含的頭文件#include <fstream>
一、C++文件操作類型
ofstream:寫入文件的操作類,從內存到硬盤(從ostream引申而來)
ifstream:讀取文件的操作類,從硬盤到內存(從istrean引申而來)
fstream:可同時寫入讀取文件的操作類(從iostream引申而來)

二、打開文件
fstream類中,成員函數fopen()用於打開文件
void open(const char* filename, int mode, int access);
參數:
filename:要打開的文件名;mode:要打開文件的方式;access:打開文件的屬性;
mode分類:
ios::app : 以追加的方式打開文件
ios::ate : 文件打開後定位到文件尾,ios:app就包含有此屬性
ios::binary : 以二進制方式打開文件,缺省的方式是文本方式
ios::in : 文件以輸入方式打開(文件數據輸入到內存)
ios::out : 文件以輸出方式打開(內存數據輸出到文件)
ios::nocreate : 不建立文件,所以文件不存在時打開失敗
ios::noreplace : 不覆蓋文件,所以打開文件時如果文件存在失敗
ios::turnc : 如果文件存在,把文件長度設爲0
打開方式可以連接使用,如ios::out|ios::binary
打開文件的屬性分類:
0 : 普通文件,打開訪問
1 : 只讀文件
2 : 隱含文件
4 : 系統文件
屬性分類可以連接使用,如1|2

打開文件實例:
fstream ExampleFile1;
ExampleFile1.open("D:\\test.txt", ios::out|ios::binary, 0);

fstream,ifstream,ofstream得成員函數open()都包含一個默認打開方式,如下所示:
ofstream ios::out|ios::turnc
ifstream ios::in
fstream ios::in|ios::out

使用成員函數bool is_open();來檢查文件是否已經打開,true爲打開成功,false爲打開失敗。

關閉文件:
當文件讀寫操作完成之後,我們必須將文件關閉以使文件重新變爲可訪問的。關閉文件需要調用成員函數close(),它負責將緩存中的數據排放出來並關閉文件。它的格式很簡單:
void close ();
這個函數一旦被調用,原先的流對象(stream object)就可以被用來打開其它的文件了,這個文件也就可以重新被其它的進程(process)所有訪問了。
爲防止流對象被銷燬時還聯繫着打開的文件,析構函數(destructor)將會自動調用關閉函數close。

向文件test.txt中寫入一些數據。
代碼如下:
int main()
{
ofstream ExampleFile("test.txt");
if (ExampleFile.is_open())
{
ExampleFile << "This is a line.\n";
ExampleFile << "This is another line .";
ExampleFile.close();
}
else
cout << "error" << endl;
return 0;
}
執行結果如下:

從test.txt文件讀取內容,並打印到屏幕上。
代碼如下:
int main()
{
char szBuff[128];
ifstream ExampleRead("test.txt");
if (!ExampleRead.is_open())
{
cout << "Error opening file!" << endl;
exit(1);
}

while (!ExampleRead.eof())
{
ExampleRead.getline(szBuff, 30);
cout << szBuff << endl;
}
return 0;
}
執行結果如下:

三、狀態標識符的驗證
eof() : 是ifstream從類ios繼承過來的,到達文件末尾時,返回true;
bad() : 讀寫過程中出錯,返回true;如對一個不是打開爲寫狀態的文件進行寫入時,寫入的設 備沒有剩餘空間的時候等。
fail() : 除了與bad() 同樣的情況下會返回 true 以外,加上格式錯誤時也返回true ,例如當想要讀入一個整數,而獲得了一個字母的時候。
good() : 如果調用以上任何一個函數返回true 的話,此函數返回 false

獲得和設置流指針(get and put stream pointers):
所有輸入/輸出流對象(i/o streams objects)都有至少一個流指針:
ifstream, 類似istream, 有一個被稱爲get pointer的指針,指向下一個將被讀取的元素。
ofstream, 類似 ostream, 有一個指針 put pointer ,指向寫入下一個元素的位置。
fstream, 類似 iostream, 同時繼承了get 和 put

流指針位置操作:
tellg() : 返回pos_type 類型的值(根據ANSI-C++ 標準) ,就是一個整數,代表當前get 流指針的位置。
tellp() : 返回pos_type 類型的值(根據ANSI-C++ 標準) ,就是一個整數,代表當前put流指針的位置 。
seekg()、seekp() : 用來改變流指針get、put的位置。被重載爲兩種不同的原型:
seekg(pos_type position);
seekp(pos_type position);
流指針被改變爲指向從文件開始計算的一個絕對位置。

seekg(off_type offset, seekdir direction);
seekp(off_type offset, seekdir direction);
指定由參數direction決定的一個具體指針開始計 算的一個位移。

參數offset類型:
與tellg()和tellp()的返回值類型相同。
參數direction類型:
ios::beg : 從流開始位置計算的位移
ios::cur : 從流指針當前位置開始計算的位移
ios::end : 從流末尾處開始計算的位移

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

四、二進制文件操作
獲取當前文件main.cpp的大小:
代碼如下:
#include <iostream>
#include <fstream>
using namespace std;

void main()
{
const char* pFileName = "main.cpp";
ifstream ExampleRead(pFileName, ios::in|ios::binary);
if (!ExampleRead.is_open())
{
cout << "Error opening file. \n";
return;
}
long lBegin = 0, lEnd = 0;
lBegin = ExampleRead.tellg();
ExampleRead.seekg(0, ios::end);
lEnd = ExampleRead.tellg();
ExampleRead.close();
cout << "size of " << pFileName << "is " << (lEnd - lBegin) << " bytes.\n" << endl;
system("pause");
return;
}

執行結果如下:


write和read函數使用:
write和read是文件流爲順序讀寫數據特殊設計的成員函數。
write(char* buffer, streamsize size); // 繼承ostream,順序寫
read(char* buffer, streamsize size); // 繼承istream,順序讀

使用read()從test.txt文件中讀取內容並顯示到屏幕
代碼如下:
void main()
{
const char* pFileName = "test.txt";
ifstream ExampleRead(pFileName, ios::in | ios::binary | ios::ate);
if (!ExampleRead.is_open())
{
cout << "Error opening file.\n";
exit(1);
}
long lSize = ExampleRead.tellg();
ExampleRead.seekg(0, ios::beg);
char* buffer;
buffer = new char[lSize + 1];
buffer[lSize] = '\0';
ExampleRead.read(buffer, lSize);
ExampleRead.close();
cout << (char*)buffer << endl;
delete[] buffer;
system("pause");
return;
}
執行結果如下:

五、緩存和同步機制
當我們對文件流進行操作的時候,它們與一個streambuf 類型的緩存(buffer)聯繫在一起。這個緩存(buffer)實際是一塊內存空間,作爲流(stream)和物理文件的媒介。例如,對於一個輸出流, 每次成員函數put (寫一個單個字符)被調用,這個字符不是直接被寫入該輸出流所對應的物理文件中的,而是首先被插入到該流的緩存(buffer)中。
當緩存被排放出來(flush)時,它裏面的所有數據或者被寫入物理媒質中(如果是一個輸出流的話),或者簡單的被抹掉(如果是一個輸入流的話)。這個過程稱爲同步(synchronization),它會在以下任一情況下發生:
當文件被關閉時: 在文件被關閉之前,所有還沒有被完全寫出或讀取的緩存都將被同步。
當緩存buffer 滿時:緩存Buffers 有一定的空間限制。當緩存滿時,它會被自動同步。
控制符明確指明:當遇到流中某些特定的控制符時,同步會發生。這些控制符包括:flush 和endl。

明確調用函數sync(): 調用成員函數sync() (無參數)可以引發立即同步。這個函數返回一個int 值,等於-1 表示流沒有聯繫的緩存或操作失敗
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章