瑞安外貿(mào)網(wǎng)站制作網(wǎng)站管理系統(tǒng)
一、寫入文本文件
文本文件一般以行的形式組織數(shù)據(jù)。
包含頭文件:#include <fstream>
類:ofstream(output file stream)
ofstream 打開文件的模式(方式):類內(nèi)open()成員函數(shù)參數(shù)2.參數(shù)1是文件存儲(chǔ)/創(chuàng)建路徑
例如:fout.open(filename,ios::app);
對(duì)于 ofstream,不管用哪種模式打開文件,如果文件不存在,都會(huì)創(chuàng)建文件。
ios::out 缺省值:會(huì)截?cái)辔募?nèi)容。
ios::trunc 截?cái)辔募?nèi)容。(truncate)
ios::app 不截?cái)辔募?nèi)容,只在文件未尾追加文件。(append)
主要關(guān)注路徑與文件名書寫方法,推薦使用原始字面量和絕對(duì)路徑,還有打開寫入關(guān)閉等操作。
具體演示和步驟如下:
#include <iostream>
#include <fstream> // ofstream 類需要包含的頭文件。
using namespace std;
int main()
{
// 文件名一般用全路徑,書寫的方法如下:
// 1)"D:\data\txt\test.txt" // 錯(cuò)誤。
// 2)R"(D:\data\txt\test.txt)" // 原始字面量,C++11 標(biāo)準(zhǔn)。
// 3)"D:\\data\\txt\\test.txt" // 轉(zhuǎn)義字符。
// 4)"D:/tata/txt/test.txt" // 把斜線反著寫。
// 5)"/data/txt/test.txt" // Linux 系統(tǒng)采用的方法。
string filename = R"(D:\data\txt\test.txt)";
//char filename[] = R"(D:\data\txt\test.txt)";
// 創(chuàng)建文件輸出流對(duì)象,打開文件,如果文件不存在,則創(chuàng)建它。
// ios::out 缺省值:會(huì)截?cái)辔募?nèi)容。
// ios::trunc 截?cái)辔募?nèi)容。(truncate)
// ios::app 不截?cái)辔募?nèi)容,只在文件未尾追加文件。(append)
//ofstream fout(filename);
//ofstream fout(filename, ios::out);
//ofstream fout(filename, ios::trunc);
//ofstream fout(filename, ios::app);
ofstream fout;
fout.open(filename,ios::app);
// 判斷打開文件是否成功。
// 失敗的原因主要有:1)目錄不存在;2)磁盤空間已滿;3)沒有權(quán)限,Linux 平臺(tái)下很常見。
if (fout.is_open() == false)
{
cout << "打開文件" << filename << "失敗。\n"; return 0;
}
// 向文件中寫入數(shù)據(jù)。
fout << "test1\n";
fout << "test2\n";
fout << "test3\n";
fout.close(); // 關(guān)閉文件,fout 對(duì)象失效前會(huì)自動(dòng)調(diào)用 close()。
cout << "操作文件完成。\n";
}
二、讀取文本文件
包含頭文件:#include <fstream>
類:ifstream
ifstream 打開文件的模式(方式):
對(duì)于 ifstream,如果文件不存在,則打開文件失敗。
ios::in 缺省值。
重點(diǎn)在于讀取方法,具體演示如下:
#include <iostream>
#include <fstream> // ifstream 類需要包含的頭文件。
#include <string> // getline()函數(shù)需要包含的頭文件。
using namespace std;
int main()
{
// 文件名一般用全路徑,書寫的方法如下:
// 1)"D:\data\txt\test.txt" // 錯(cuò)誤。
// 2)R"(D:\data\txt\test.txt)" // 原始字面量,C++11 標(biāo)準(zhǔn)。
// 3)"D:\\data\\txt\\test.txt" // 轉(zhuǎn)義字符。
// 4)"D:/tata/txt/test.txt" // 把斜線反著寫。
// 5)"/data/txt/test.txt" // Linux 系統(tǒng)采用的方法。
string filename = R"(D:\data\txt\test.txt)";
//char filename[] = R"(D:\data\txt\test.txt)";
// 創(chuàng)建文件輸入流對(duì)象,打開文件,如果文件不存在,則打開文件失敗。。
// ios::in 缺省值。
//ifstream fin(filename);
//ifstream fin(filename, ios::in);
ifstream fin;
fin.open(filename,ios::in);
// 判斷打開文件是否成功。
// 失敗的原因主要有:1)目錄不存在;2)文件不存在;3)沒有權(quán)限,Linux 平臺(tái)下很常見。
if (fin.is_open() == false)
{
cout << "打開文件" << filename << "失敗。\n"; return 0;
}第一種方法。
//string buffer; // 用于存放從文件中讀取的內(nèi)容。文本文件一般以行的方式組織數(shù)據(jù)。
//while (getline(fin, buffer))
//{
// cout << buffer << endl;
//}第二種方法。
//char buffer[16]; // 存放從文件中讀取的內(nèi)容。注意:如果采用 ifstream.getline(),一定要保證緩沖區(qū)足夠大。
//while (fin.getline(buffer, 15))
//{
// cout << buffer << endl;
//}
// 第三種方法。
string buffer;
while (fin >> buffer)
{
cout << buffer << endl;
}
fin.close(); // 關(guān)閉文件,fin 對(duì)象失效前會(huì)自動(dòng)調(diào)用 close()。
cout << "操作文件完成。\n";
}
三、讀寫二進(jìn)制文件
包含頭文件:#include <fstream>
類:ofstream(output file stream)
ofstream 打開文件的模式(方式):
對(duì)于 ofstream,不管用哪種模式打開文件,如果文件不存在,都會(huì)創(chuàng)建文件。
ios::out 缺省值:會(huì)截?cái)辔募?nèi)容。
ios::trunc 截?cái)辔募?nèi)容。(truncate)
ios::app 不截?cái)辔募?nèi)容,只在文件未尾追加文件。(append)
ios::binary 以二進(jìn)制方式打開文件。
操作文本文件和二進(jìn)制文件的一些細(xì)節(jié):
1)在 windows 平臺(tái)下,文本文件的換行標(biāo)志是"\r\n"。
2)在 linux 平臺(tái)下,文本文件的換行標(biāo)志是"\n"。
3)在 windows 平臺(tái)下,如果以文本方式打開文件,寫入數(shù)據(jù)的時(shí)候,系統(tǒng)會(huì)將"\n"轉(zhuǎn)換成
"\r\n";讀取數(shù)據(jù)的時(shí)候,系統(tǒng)會(huì)將"\r\n"轉(zhuǎn)換成"\n"。 如果以二進(jìn)制方式打開文件,寫和讀都不會(huì)進(jìn)行轉(zhuǎn)換。
4)在 Linux 平臺(tái)下,以文本或二進(jìn)制方式打開文件,系統(tǒng)不會(huì)做任何轉(zhuǎn)換。
5)以文本方式讀取文件的時(shí)候,遇到換行符停止,讀入的內(nèi)容中沒有換行符;以二制方式讀取文件的時(shí)候,遇到換行符不會(huì)停止,讀入的內(nèi)容中會(huì)包含換行符(換行符被視為數(shù)據(jù))。
6)在實(shí)際開發(fā)中,從兼容和語義考慮,一般:a)以文本模式打開文本文件,用行的方法操作它;
b)以二進(jìn)制模式打開二進(jìn)制文件,用數(shù)據(jù)塊的方法操作它;c)以二進(jìn)制模式打開文本文件和二進(jìn)制文件,用數(shù)據(jù)塊的方法操作它,這種情況表示不關(guān)心數(shù)據(jù)的內(nèi)容。(例如復(fù)制文件和傳輸文件)d)不要以文本模式打開二進(jìn)制文件,也不要用行的方法操作二進(jìn)制文件,可能會(huì)破壞二進(jìn)制數(shù)據(jù)文件的格式,也沒有必要。(因?yàn)槎M(jìn)制文件中的某字節(jié)的取值可能是換行符,但它的意義并不是換行,可能是整數(shù)n 個(gè)字節(jié)中的某個(gè)字節(jié))
fstream 打開文件的模式(方式):
對(duì)于 ifstream,如果文件不存在,則打開文件失敗。
演示:(不熟悉網(wǎng)絡(luò)通訊也可以嘗試看看這個(gè)用語發(fā)送文件的簡(jiǎn)單成員函數(shù),不用管有些沒見過的函數(shù),主要認(rèn)識(shí)二進(jìn)制數(shù)據(jù)塊讀出和寫入。)需要注意write()和read()成員函數(shù)。
bool recvfile(const string &filename,const size_t filesize){
ofstream fout(filename,ios::binary);
if(fout.is_open()==false){cout<<"打開文件失敗"<<endl;return false;}int onread=0;//每次調(diào)用fin.read()打算讀取的字節(jié)數(shù)
int totalbytes=0;//從文件中已讀取的總字節(jié)數(shù)
char buffer[4096];//每次存放讀取數(shù)據(jù)的字節(jié)數(shù)while(true){//計(jì)算本次應(yīng)接收數(shù)據(jù)的字節(jié)數(shù)
if(filesize-totalbytes>4096)onread=4096;
else onread=filesize-totalbytes;if(recv(buffer,onread)==false)return false;//接收文件數(shù)據(jù)fout.write(buffer,onread);//將接收的文件寫入
totalbytes+=onread;//更新已接收文件字節(jié)數(shù)if(filesize==totalbytes)break;
}
return true;
}
//向服務(wù)端發(fā)送文件內(nèi)容
bool sendfile(const string& filename,const size_t filesize){
//以二進(jìn)制的方法打開文件
ifstream fin(filename,ios::binary);
if(fin.is_open()==false){cout<<"打開文件:"<<filename<<"失敗\n"<<endl;return false;}int onread=0; //每次調(diào)用fin.read()打算讀取的字節(jié)數(shù)
int totalbytes=0;//從文件中已讀取的總字節(jié)數(shù)
char buffer[4096];//每次存放讀取數(shù)據(jù)的字節(jié)數(shù)while(true){
if(filesize-totalbytes>4096)onread=4096;//如果剩余數(shù)據(jù)字節(jié)數(shù)大于4096,則這次循環(huán)打算讀取的數(shù)據(jù)字節(jié)數(shù)為4096
else onread=filesize-totalbytes;//否則就讀取剩余數(shù)據(jù)的字節(jié)數(shù)fin.read(buffer,onread);//讀取數(shù)據(jù)并存入bufferif(send(buffer,onread)==false)//向服務(wù)端發(fā)送數(shù)據(jù)return false;
totalbytes+=onread;//更新已讀數(shù)據(jù)量
if(totalbytes==filesize)break;//如果全部數(shù)據(jù)讀取完break
}
return true;
}
三、隨機(jī)存取
1.fstream 類
fstream 類既可以讀文本/二進(jìn)制文件,也可以寫文本/二進(jìn)制文件。
fstream 類的缺省模式是 ios::in | ios::out,如果文件不存在,則創(chuàng)建文件;但是,不會(huì)清空文件原
有的內(nèi)容。
普遍的做法是:
1)如果只想寫入數(shù)據(jù),用 ofstream;如果只想讀取數(shù)據(jù),用 ifstream;如果想寫和讀數(shù)據(jù),用 fst
ream,這種情況不多見。不同的類體現(xiàn)不同的語義。
2)在 Linux 平臺(tái)下,文件的寫和讀有嚴(yán)格的權(quán)限控制。(需要的權(quán)限越少越好)
2.文件的位置指針
對(duì)文件進(jìn)行讀/寫操作時(shí),文件的位置指針指向當(dāng)前文件讀/寫的位置。不論讀還是寫所使用的類以及相關(guān)函數(shù),文件位置指針有且只有一個(gè),所有操作都在使用這一個(gè)指針,沒有讀指針和寫指針這種說法。
1)獲取文件位置指針
ofstream 類的成員函數(shù)是 tellp();ifstream 類的成員函數(shù)是 tellg();fstream 類兩個(gè)都有,效果相
同。
std::streampos tellp();
std::streampos tellg();
2)移動(dòng)文件位置指針
ofstream 類的函數(shù)是 seekp();ifstream 類的函數(shù)是 seekg();fstream 類兩個(gè)都有,效果相同。
方法一:
std::istream & seekg(std::streampos _Pos);
fin.seekg(128); // 把文件指針移到第 128 字節(jié)。
fin.seekp(128); // 把文件指針移到第 128 字節(jié)。
fin.seekg(ios::beg) // 把文件指針移動(dòng)文件的開始。
fin.seekp(ios::end) // 把文件指針移動(dòng)文件的結(jié)尾。
方法二:
std::istream & seekg(std::streamoff _Off,std::ios::seekdir _Way);
在 ios 中定義的枚舉類型:
enum seek_dir {beg, cur, end}; // beg-文件的起始位置;cur-文件的當(dāng)前位置;end-文件的結(jié)尾位置。
fin.seekg(30, ios::beg); // 從文件開始的位置往后移 30 字節(jié)。
fin.seekg(-5, ios::cur); // 從當(dāng)前位置往前移 5 字節(jié)。
fin.seekg( 8, ios::cur); // 從當(dāng)前位置往后移 8 字節(jié)。
fin.seekg(-10, ios::end); // 從文件結(jié)尾的位置往前移 10 字節(jié)。
2)隨機(jī)存取
是指直接移動(dòng)文件的位置指針,在指定位置讀取/寫入數(shù)據(jù)?,F(xiàn)在再來看:
ios::out 1)會(huì)截?cái)辔募?#xff1b;2)可以用 seekp()移動(dòng)文件指針。
ios:trunc 1)會(huì)截?cái)辔募?#xff1b;2)可以用 seekp()移動(dòng)文件指針。
ios::app 1)不會(huì)截?cái)辔募?#xff1b;2)文件指針始終在文件未尾,不能用 seekp()移動(dòng)文件指針。
ios::ate 打開文件時(shí)文件指針指向文件末尾,但是,可以在文件中的任何地方寫數(shù)據(jù)。
ios::in 打開文件進(jìn)行讀操作,即讀取文件中的數(shù)據(jù)。
ios::binary 打開文件為二進(jìn)制文件,否則為文本文件。
注:ate 是 at end 的縮寫,trunc 是 truncate(截?cái)?#xff09;的縮寫,app 是 append(追加)的縮寫。
四、緩沖區(qū)及流狀態(tài)
1.文件緩沖區(qū)
文件緩沖區(qū)(緩存)是系統(tǒng)預(yù)留的內(nèi)存空間,用于存放輸入或輸出的數(shù)據(jù)。
根據(jù)輸出和輸入流,分為輸出緩沖區(qū)和輸入緩沖區(qū)。
注意,在 C++中,每打開一個(gè)文件,系統(tǒng)就會(huì)為它分配緩沖區(qū)。不同的流,緩沖區(qū)是獨(dú)立的。
一般來說不用關(guān)心輸入緩沖區(qū),只關(guān)心輸出緩沖區(qū)就行了。
在缺省模式下,輸出緩沖區(qū)中的數(shù)據(jù)滿了才把數(shù)據(jù)寫入磁盤,但是,這種模式不一定能滿足業(yè)務(wù)的
需求。
輸出緩沖區(qū)的操作:
1)flush()成員函數(shù)
刷新緩沖區(qū),把緩沖區(qū)中的內(nèi)容寫入磁盤文件。
2)endl? 換行,然后刷新緩沖區(qū)。
3)unitbuf
fout << unitbuf;
設(shè)置 fout 輸出流,在每次操作之后自動(dòng)刷新緩沖區(qū)。
4)nounitbuf
fout << nounitbuf;
設(shè)置 fout 輸出流,讓 fout 回到缺省的緩沖方式。
2.流狀態(tài)
流狀態(tài)有三個(gè):eofbit、badbit 和 failbit,取值:1-設(shè)置;或 0-清除。
當(dāng)三個(gè)流狀成都為 0 時(shí),表示一切順利,good()成員函數(shù)返回 true。
1)eofbit
當(dāng)輸入流操作到達(dá)文件未尾時(shí),將設(shè)置 eofbit。
eof()成員函數(shù)檢查流是否設(shè)置了 eofbit。
2)badbit
無法診斷的失敗破壞流時(shí),將設(shè)置 badbit。(例如:對(duì)輸入流進(jìn)行寫入;磁盤沒有剩余空間)。
bad()成員函數(shù)檢查流是否設(shè)置了 badbit。
3)failbit
當(dāng)輸入流操作未能讀取預(yù)期的字符時(shí),將設(shè)置 failbit(非致命錯(cuò)誤,可挽回,一般是軟件錯(cuò)誤,例
如:想讀取一個(gè)整數(shù),但內(nèi)容是一個(gè)字符串;文件到了未尾)I/O 失敗也可能設(shè)置 failbit。
fail()成員函數(shù)檢查流是否設(shè)置了 failbit。
4)clear()成員函數(shù)清理流狀態(tài)。
5)setstate()成員函數(shù)重置流狀態(tài)。