C語言使用FILE對文件進行操作,常用到的函數有fopen()、freopen()、fread()、fwrite()、fclose()等,分別用來打開文件、讀寫文件、關閉文件。
C++可以使用fstream文件流對文件進行操作,使用時需要引入頭文件:#include <fstream>。可以使用ifstream、ofstream、fstream文件流對文件進行輸入(讀)、輸出(寫)、輸入輸出(讀寫)操作。Ifstream支持>>操作,ofstream支持<<操作,fstream同時支持>>和<<操作。
本文簡單介紹C++文件流的操作:
目錄
一、打開、關閉文件
- 打開文件 fstream可以在聲明流對象時傳入文件名打開文件,也可以使用open()函數打開文件。
- 關閉文件 文件打開后必須關閉,fstream提供close()函數關閉文件。
打開文件
- 使用構造函數聲明對象時打開文件,示例:
fstream file(filename, ios::in | ios::out);
- 使用open()函數打開文件,函數原型:
void open(const char* filename,int mode,int access); // filename—文件名;mode—打開文件的模式;access—文件屬性
如果只傳入文件名,系統會自動根據文件類型選擇默認的打開模式。
打開文件模式mode及文件屬性access取值如下:
| mode | 打開文件模式 | 說明 | access |
文件屬性 | 說明 |
| ios::app | 以追加的方式打開文件 | 0 | 普通文件,打開訪問 | ||
| ios::ate | 文件打開后定位到文件尾,ios::app包含此屬性 | ||||
| ios::binary | 以二進制方式打開文件,默認是文本文件 | 1 | 只讀文件 | ||
| ios::in | 以輸入方式打開,讀出文件內容 | ||||
| ios::out | 以輸出方式打開,寫入文件內容 | 2 | 隱含文件 | ||
| ios::nocreate | 以不創建文件的方式打開文件,如果文件不存在,打開失敗 | ||||
| ios::noreplace | 以不覆蓋的方式打開文件,如果文件存在,打開失敗 | 4 | 系統文件 | ||
| ios::trunc | 如果文件存在,清空文件內容 |
說明:
- 模式和屬性可以單獨使用給,也可以混合使用。混合使用時,用邏輯連接符或 |連接。
- ios::out模式默認會清空,即iios::out|ios::trunc和ios::out打開文件時都會清空文件。如果不想清空文件,那么設置讀寫模式為ios::out|ios::app,以這種模式打開文件后,數據會以追加的方式寫入到文件。
二、 讀寫文件
fstream提供的讀寫操作有:<<、>>、read()、write()、put()、get()、getline()。根據文件類型可分為文本文件和二進制文件,根據讀寫方式可分為逐行讀寫和整塊讀寫。通常,文本文件使用逐行讀寫的方式,二進制文件使用整塊讀寫的方式。
1. 文本文件讀寫
文本文件通常使用逐行讀寫的方式。逐行讀取文本文件時可以使用getline()函數。系統庫和fstream都提供了同名的getline()函數,不同點在於fstream文件流提供的getline()函數是C語言格式的,而系統庫提供的getline()函數是C++格式的,如下:
| fstream提供的getline()函數 |
系統庫提供的getline()函數 |
| ifstream in(“test.txt”); char temp[1024]’ while(!in.eof()) { in.getline(temp,1024); } |
ifstream in(text.txt); std::string strline; while(!in.eof()) { getline(in,strline); } |
逐行寫入文本文件可以使用操作符<<。
2. 二進制文件的讀寫
二進制文件通常整塊讀取或寫入,當然也可以讀寫單個字符,用到的函數包括:put()、get()、read()、write()。
通常使用write()、put()函數寫入二進制文件。使用read()、get()讀取二進制文件。
- 讀寫數據塊
使用read()和write()函數讀寫數據塊,原型如下:
istream& read(char* buffer,int count); ofstream& write(char* buffer,int count); //從buf指向的緩存向文件寫入count個字符。
需要注意的是:read()函數從文件中讀取count個字符,讀取到buffer指向的緩存中,如果還未讀入num個字符就到了文件尾,可以用成員函數gcount()獲取實際讀取的字符數。
- 讀寫單個字符
通常使用get()、put()函數讀寫單個字符
put()函數向文件寫入一個字符,原型為ofstream& put(char ch);
get()函數從文件讀取一個字符,有三種重載形式:
① ifstream& get(char& ch); 從流中讀取一個字符,如果到文件尾,返回空字符。
② int get(); 從流中返回一個字符,如果到達文件尾,返回EOF,
③ ifstream& get(char* buf,int count,char delim=”\n; 把字符讀入buf指向的緩存中,知道讀入了count個字符或者遇到delim指定的字符。
三、 定位文件指針、獲取文件大小
C++的文件定位分為讀位置和寫位置的定位,對應的成員函數分別為seekg()和seekp()。
seekg()函數設置讀位置,seekp()設置寫位置。函數原型如下:
istream& seekg(streamoff offset,seek_dir origin);
ofstream& seekp(streamoff offset,seek_dir origin);
offset表示偏移量,seek_dir表示移動的基准位置,取值如下:
ios::beg 文件開頭
ios::cur 文件當前位置
ios::end 文件結尾
示例:
inFile.seekg(12,ios::beg); // 把文件讀指針從開始位置向后移動12個字節 outFile.seekp(12,ios::cur); // 把文件寫指針從當前位置向后移動12個字節
獲取文件大小可以使用seekg()和tellg()或者seekp()和tellp()函數結合使用的方式獲取文件大小。
示例:
inFile.seekg(0,ios::end); // 讀文件指針移動到文件末尾 streampos ipos = inFile.tellg(); //返回當前指針的位置,也就是文件的大小,單位是字節
四、 示例代碼
//讀寫txt文件 std::string in_read_txt = "in_read.txt"; std::ifstream file_in_read_txt(in_read_txt); // 讀取文件 // 文本文件逐行讀取數據 if(!file_in_read_txt.is_open()) // 判斷文件是否打開 { std::string sErrmsg = "Open File FAIL"; throw sErrmsg; } std::string strline; std::vector<std::string> vecLine; while (getline(file_in_read_txt,strline)) { // 逐行獲取txt內容 std::cout << strline << std::endl; vecLine.push_back(strline); } file_in_read_txt.close(); // 文本文件逐行寫入 std::string out_write_txt = "out_write.txt"; std::ofstream file_out_write_txt(out_write_txt,std::ios::trunc); // 寫入txt文件 if(!file_out_write_txt.is_open()) { std::string sErrmsg = "Open File FAIL"; throw sErrmsg; } for(std::string& line : vecLine) { file_out_write_txt << line << std::endl; //逐行寫入文件 } file_out_write_txt.close(); std::string in_read_bin = "in_read.bin"; std::string out_write_bin = "out_write.bin"; std::ifstream file_in_read_bin(in_read_bin,std::ios::binary); // 以二進制方式讀取文件 std::ofstream file_out_write_bin(out_write_bin,std::ios::binary); // 以二進制方式寫入文件 // 二進制文件獲取數據 if(!file_in_read_bin.is_open()) { std::string sErrmsg = "Open File FAIL"; throw sErrmsg; } uchar binData[2048] = {0}; file_in_read_bin.read((char*)binData,sizeof(binData)); int iDataSize = file_in_read_bin.gcount(); printf("Read Data Size = %d\n",iDataSize); for(int i=0;i<iDataSize;i++) { printf("0x%04x,0x%02x\n",i,binData[i]); } //使用get()函數獲取文件內容 // char chTemp; // 第一種用法 // while (file_in_read_bin.get(chTemp)) { // printf("0x%02x\n",(uchar)chTemp); // } // 第二種用法 // for(int i=0;i<1372;i++) // { // chTemp = file_in_read_bin.get(); // printf("0x%02x\n",(uchar)chTemp); // } // 第三種用法 // file_in_read_bin.get((char*)binData,sizeof(binData)); // for(int i=0;i<sizeof(binData);i++) // { // printf("0x%04x,0x%02x\n",i,binData[i]); // } file_in_read_bin.close(); // 寫入bin文件 if(!file_out_write_bin.is_open()) { std::string sErrmsg = "Open File FAIL"; throw sErrmsg; } file_out_write_bin.write((char*)binData,iDataSize); file_out_write_bin.close();
