C++文件讀寫
本文主要用於探討使用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;
}