本文主要用於探討使用C++來進行檔案讀寫操作。
在C++中,所有的輸入輸出操作大部分都繼承自 ios_base 基類,詳細的繼承體系如下圖所示
fstream的使用
在fstream類中,成員函式open()
實現開啟檔案的操作,從而將資料流和檔案進行關聯,通過ofstream,ifstream,fstream物件進行對檔案的讀寫操作,同時在開啟檔案時,可以指定開啟的模式,如讀、寫或者讀寫,可選模式如下
mode | detail |
---|---|
ios::in | 為輸入(讀)而開啟檔案 |
ios::out | 為輸出(寫)而開啟檔案 |
ios::ate | 初始位置:檔案尾 |
ios::app | 所有輸出附加在檔案末尾 |
ios::trunc | 如果檔案已存在則先刪除該檔案 |
ios::binary | 二進位制方式 |
open的定義方式
void open(const wchar_t *_Filename,
ios_base::openmode mode= ios_base::in | ios_base::out;
void open(const wchar_t *_Filename,
ios_base::openmode mode= ios_base::in | ios_base::out,
int prot = ios_base::_Openprot);
其中,filename表示操作檔名,mode表示開啟檔案的方式,prot表示開啟檔案的屬性。在開啟檔案時,在stream類的建構函式中呼叫open()函式都有自己預設的操作方式
ofstream out("...", ios::out);
ifstream in("...", ios::in);
fstream foi("...", ios::in|ios::out);
使用write()
和read()
函式進行檔案讀寫
int main(){
string file_path = "test.txt";
char info[] = "hello fan";
char buffer[256];
ofstream out(file_path, ios::binary);
if(out.is_open()){
out.write(info, sizeof(info));
out.close();
}
ifstream in(file_path, ios::binary);
if(in.is_open()){
while(!in.eof()){
in.read(buffer, 100);
cout << buffer << endl;
}
in.close();
}
return 0;
}
// out
/*
hello fan
*/
ofstream過載了 <<
操作符可用來向檔案輸出資料,ifstream過載了>>
操作符,可用來讀入資料。
#include <iostream>
#include<fstream>
#include<string>
using namespace std;
int main(){
string file_path = "test.txt";
char buffer[256];
ofstream out(file_path);
if(out.is_open()){
out << "hello ";
out << "fan";
out.close();
}
ifstream in(file_path);
if(in.is_open()){
while(!in.eof()){
in.getline(buffer, 100);
cout << buffer << endl;
}
}
return 0;
}
// hello fan
在上述程式碼中,使用is_open()
函式,用來判斷檔案是否正常開啟,eof()
函式用來判斷是否讀到檔案末尾。
除了這些以外,還有一些驗證流的狀態的成員函式(所有都返回bool型返回值):
-
bad()
如果在讀寫過程中出錯,返回 true 。例如:當我們要對一個不是開啟為寫狀態的檔案進行寫入時,或者我們要寫入的裝置沒有剩餘空間的時候。 -
fail()
除了與bad() 同樣的情況下會返回 true 以外,加上格式錯誤時也返回true ,例如當想要讀入一個整數,而獲得了一個字母的時候。 -
good()
這是最通用的:如果呼叫以上任何一個函式返回true 的話,此函式返回 false 。
為了能夠更為方便地對檔案進行操作,還需要能夠判斷我們讀檔案讀到了哪裡,使用函式tellg/tellp
用於提取當前檔案指標的位置,使用函式 seekg/seekp
來將檔案指標移到某處
-
tellg() 和 tellp()
這兩個成員函式不用傳入引數,返回pos_type 型別的值(根據ANSI-C++ 標準) ,就是一個整數,代表當前get 流指標的位置 (用tellg) 或 put 流指標的位置(用tellp). -
seekg() 和seekp()
這對函式分別用來改變流指標get 和put的位置。兩個函式都被過載為兩種不同的原型:
seekg ( pos_type position );
seekp ( pos_type position );
使用這個原型,流指標被改變為指向從檔案開始計算的一個絕對位置。要求傳入的引數型別與函式 tellg 和tellp 的返回值型別相同。
seekg ( off_type offset, seekdir direction );
seekp ( off_type offset, seekdir direction );
使用這個原型可以指定由引數direction決定的一個具體的指標開始計算的一個位移(offset)。它可以是:
type | detail |
---|---|
ios::beg | 從流開始位置計算的位移 |
ios::cur | 從流指標當前位置開始計算的位移 |
ios::end | 從流末尾處開始計算的位移 |
示例
int main(){
string file_path = "test.txt";
char buffer[256];
ifstream in(file_path);
if(in.is_open()){
auto site = in.tellg();
in.seekg(site+6, ios::cur);
while(!in.eof()){
in.getline(buffer, 100);
cout << buffer << endl;
}
}
return 0;
}
上述檔案中資料為 "hello fan",輸出為 "fan",因為開始時,檔案指標指向檔案開頭,使用tellg()
函式獲取檔案指標位置,然後使用seekg()
函式將檔案指標後移6個字元,因此讀取結果為 "fan"。
簡單檔案讀寫示例
#include <iostream>
#include<fstream>
#include<string>
using namespace std;
int choose_mod(){
int f = 0;
cout << "----Easy file read and write----" << endl;
cout << "Please choose write or read file" << endl;
cout << "Enter 1, read file" << endl;
cout << "Enter 2, write file" << endl;
cout << "Enter 3, exit" << endl;
cout << "--------------------------------" << endl;
cin >> f;
while(f != 1 && f != 2 && f != 3){
cout << "Please choose 1 or 2 or 3" << endl;
cin >> f;
}
}
int main(){
string file_name = "test.txt";
int mod = choose_mod();
char buffer[256];
ifstream in;
ofstream out;
string tmp;
while(mod != 3){
if(mod == 1){
in.open(file_name);
if(in.is_open()){
while(!in.eof()){
in.getline(buffer, 100);
cout << buffer << endl;
}
in.close();
}
}else{
out.open(file_name, ios::app);
if(out.is_open()){
cout << "Please enter string, Enter quit end" << endl;
tmp = "";
while(true){
getline(cin, tmp);
if(tmp == "quit") break;
out << tmp << "\n";
}
out.close();
}
}
mod = choose_mod();
}
cout << "Quit" << endl;
return 0;
}