文件流
myfstream
fstream Test
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream fs("bbb.txt", ios::in | ios::out | ios::trunc);
if(!fs)
cout << "open error" << endl;
fs.put('a');
fs.put('b');
fs.put('c');
fs.put('d');
fs.seekp(0, ios::beg);
char ch;
while (fs.get(ch),!fs.eof())
{
cout << ch;
}
fs.close();
return 0;
}
運行結果爲:
myfstream
自實現對 FILE*fp 的包裝,實現對象對文件的訪問。實現成員函數 put/get 函數。
自實現封裝的時候最核心的是句柄,在這裏核心句柄就是FILE * pf
讀者可以自行模仿上面代碼進行實現。
fstream
對文件的操作是由文件流類完成的。文件流類在流與文件間建立連接。由於文件流分爲三種:文件輸入流、文件輸出流、文件輸入/輸出流,所以相應的必須將文件流說明爲ifstream、ofstream 和 fstream 類的對象,然後利用文件流的對象對文件進行操作。
對文件的操作過程可按照以下四步進行:即定義文件流類的對象、打開文件、對文件進行讀寫操作、關閉文件,下面分別進行說明。
流對象的定義
//流類 流對象;
ifstream ifile; //定義一個文件輸入流對象
ofstream ofile; //定義一個文件輸出流對象
fstream iofile; //定義一個文件輸出/輸入流對象
一般情況下在定義對象的時候指定文件和權限,也有一種或情況不指定文件和權限:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream fs;
fs.open("abc.txt", ios::in | ios::out | ios::trunc);
if(!fs)
cout << "open error" << endl;
return 0;
}
那麼爲什麼不使用open函數的返回值呢?
流對象關聯文件
open 函數
定義了文件流對象後,就可以利用其成員函數 open()打開需要操作的文件,該成員函數的函數原型爲:
void open(const unsigned char *filename,int mode,int access=filebuf:openprot);
其中:filename 是一個字符型指針,指定了要打開的文件名;mode 指定了文件的打開方式,其值如下表所示;access 指定了文件的系統屬性,取默認即可。並且open函數返回值爲void類型,所以不能使用open函數的返回值進行判斷。
打開方式
幾點說明:
① 在實際使用過程中,可以根據需要將以上打開文件的方式用"|" 組合起來。如:
ios::in|ios::out 表示以讀/寫方式打開文件
ios::in|ios:: binary 表示以二進制讀方式打開文件
ios::out|ios:: binary 表示以二進制寫方式打開文件
ios::in|ios::out|ios::binary 表示以二進制讀/寫方式打開文件
② 如果未指明以二進制方式打開文件,則默認是以文本方式打開文件。
③ 構造函數打開文件
對於 ifstream 流, mode 參數的默認值爲 ios::in,
對於 ofstream 流,mode 的默 認值爲 ios::out|ios::trunc,
對於 fstream 流, mode 的默認值爲 ios::int|ios::out|ios::app
④ ios::int|ios::out 是什麼?
是命名空間的 ios 中一堆枚舉。
關閉流對象
在文件操作結束(即讀、寫完畢)時應及時調用成員函數 close()來關閉文件。該函數比較簡單,沒有參數和返回值。
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream fs;
fs.open("abc.txt", ios::in | ios::out | ios::trunc);
if(!fs)
cout << "open error" << endl;
fs.close(); //關閉流對象
return 0;
}
文件讀寫
讀寫文本文件
讀寫接口
讀一字/行
一次讀取一個字符
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream fs;
fs.open("abc.txt", ios::in | ios::out | ios::trunc);
if(!fs)
cout << "open error" << endl;
for (char i = 'a'; i < 'z'; i++)
fs.put(i);
fs.seekp(0, ios::beg);
char ch;
while (fs.get(ch))
cout << ch << endl;
fs.close();
return 0;
}
運行結果爲:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream fs;
fs.open("abc.txt", ios::in | ios::out | ios::trunc);
if(!fs)
cout << "open error" << endl;
for (char i = 'a'; i < 'z'; i++)
fs << i;
fs.seekp(0, ios::beg);
char ch;
while (fs>>ch)
cout << ch << endl;
fs.close();
return 0;
}
運行結果爲:
一次讀寫一行
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream fs;
fs.open("abc.txt", ios::in | ios::out | ios::trunc);
if(!fs)
cout << "open error" << endl;
fs << "aaaaaaaaaaa" << endl;
fs << "bbbbbbbbbbb" << endl;
fs << "ccccccccccc" << endl;
fs.seekp(0, ios::beg);
char buf[1024];
while (fs>>buf)
cout << buf << endl;
fs.close();
return 0;
}
運行結果爲:
上面一次讀取一行的用法有缺陷,如果超過1024個,程序就會崩潰。
讀寫二進制文件
讀寫接口
讀寫結構體
#include <iostream>
#include <fstream>
using namespace std;
struct Student
{
char name[100];
int num;
int age;
char sex;
};
int main()
{
fstream fs;
fs.open("add.txt", ios::in | ios::out | ios::trunc | ios::binary);
if (!fs)
cout << "open error" << endl;
Student s[3] =
{
{"li",1001,18,'f'},
{"Fun",1002,19,'m'},
{"Wang",1004,17,'f'}
};
fs.write((char*)&s, sizeof(s));
fs.seekg(0, ios::beg);
Student ss;
while (fs.read((char*)&ss, sizeof(Student)), !fs.eof())
{
cout << "Name " << ss.name << endl;
cout << "Num " << ss.num << endl;
cout << "Age " << ss.age << endl;
cout << "Sex " << ss.sex << endl;
cout << "---------------" << endl;
}
return 0;
}
運行結果爲:
隨機文件讀寫
與文件指針相關的函數
g 代表 get 的意思用於輸入的函數。p 代表 put 的意思,用於輸出函數。如果既是可輸
入又是可輸出的文件,則任意使用。
參照位置
代碼示例
infile.seekg(100); //輸入文件中的指針向前移到 100 個字節的位置
infile.seekg(-50,ios::cur); //輸入文件中的指針從當前位置後移 50 個字節
outfile.seekp(-75,iso::end); //輸出文件中指針從文件尾後移 75 個字節