一、ifstream
ifstream只能定义文件输入流对象:
#include<iostream>
#include<fstream>
using namespace std;
int main() {
ifstream fs("abc.txt");
if (!fs)
cout << "open error" << endl;
else
cout << "open success" << endl;
char ch;
while (fs.get(ch), !fs.eof())
cout << ch;
cout << endl;
system("pause");
return 0;
}
由于fs是文件输入流对象,因此不能通过fs向文件abc.txt中写入文本,只能从abc.txt中读取文本,首先先手动在abc.txt中添加文本,在hello world最后有一个回车符。
输出结果:
注意:
1、当文件输入流对象fs打开一个不存在的文件时,会跳到open error的输出中,打开失败,也就是说文件输入流对象对不存在的文件并不会去生成这个文件,只有当文件存在时,才可以成功打开。
2、这里可以用过if(!fs)来判断文件是否成功打开,表示ifstream重载了运算符!。
二、ofstream
ofstream只能定义文件输出流对象:
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
int main() {
ifstream fsr("abc.txt");
if (!fsr)
cout << "open error" << endl;
else
cout << "open success" << endl;
ofstream fsw("bca.txt");
if (!fsw)
cout << "open error" << endl;
else
cout << "open success" << endl;
char ch;
while (fsr.get(ch), !fsr.eof())
fsw.put(ch);
system("pause");
return 0;
}
把fsr打开的文件中的文本读出来,然后写入到fsw打开的文本当中去:
注意:
1、对于文件输出流对象fsw可以成功打开一个不存在的文件,若打开一个已存在的文件则会把文件里面的内容清空。
2、这里可以用过if(!fsw)来判断文件是否成功打开,表示ofstream也重载了运算符!。
三、fstream
fstream可以定义输入/输出流对象。
1、运算符重载<< 和 >>
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
int main() {
fstream fsread("read.txt", ios::in | ios::out | ios::trunc);
fstream fswrite;
fswrite.open("write.txt", ios::in | ios::out | ios::trunc);
fsread << "hello world" << endl;
fsread << "i like c" << endl;
fsread << "i lile c++" << endl;
fsread << "i like game" << endl;
fsread.seekg(0, ios::beg);
char buf[1024];
for (int i = 0; i < 4; i++) {
fsread >> buf;
cout << buf << endl;
fswrite << buf;
memset(buf, 0, sizeof(buf));
}
system("pause");
return 0;
}
<1>
fstream fsread("read.txt", ios::in | ios::out | ios::trunc);
fstream fswrite;
fswrite.open("write.txt", ios::in | ios::out | ios::trunc);
fstream可通过构造函数打开文件,也可以通过成员函数open打开文件,这里列出打开的各种方式:
说明:
1) 在实际使用过程中,可以根据需要将以上打开文件的方式用“|”组合起来。如:
ios::in|ios::out 表示以读/写方式打开文件
ios::in|ios:: binary 表示以二进制读方式打开文件
ios::out|ios:: binary 表示以二进制写方式打开文件
ios::in|ios::out|ios::binary 表示以二进制读/写方式打开文件
2) 如果未指明以二进制方式打开文件,则默认是以文本方式打开文件。
3) 对于 ifstream 流, mode 参数的默认值为 ios::in,
对于 ofstream 流,mode 的默 认值为 ios::out|ios::trunc,
对于 fstream 流, mode 的默认值为 ios::int|ios::out|ios::app
4) 也可以通过,构造函数打开文件。
5) 出错处理是通过,对类对象进行判断的。若文件打开成功,返回 1,否则返回 0
<2>
fsread << "hello world" << endl;
fsread << "i like c" << endl;
fsread << "i lile c++" << endl;
fsread << "i like game" << endl;
通过运算符重载<<向fsread流对象中写入文本。
<3>
fsread.seekg(0, ios::beg);
将当前文件指针指回到文本开始处。
与文件指针相关的函数:
seek和tell最后的字母g表示get,p表示out,对于ifstream定义得输入流对象只能用tellg, seekg;ofstream定义的输出流对象只能用tellp, seekp函数,对于fstream定义的输入输出流对象都可以使用。
参照位置:
<4>
for (int i = 0; i < 4; i++) {
fsread >> buf;
cout << buf << endl;
fswrite << buf;
memset(buf, 0, sizeof(buf));
}
这里通过运算符重载的目的是将fsread流对象打开的文本内容复制到fswrite打开的文件中。
输出结果:
可以看到当fsread流到buf中去时,遇到空格就停止流入了,这是之前提到过的流对象重载运算符>>的缺陷,所以同样这里也是用成员函数来解决。
2、成员函数get
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
int main() {
#if 0
ifstream fsr("abc.txt");
if (!fsr)
cout << "open error" << endl;
else
cout << "open success" << endl;
ofstream fsw("bca.txt");
if (!fsw)
cout << "open error" << endl;
else
cout << "open success" << endl;
/*char buf[1024];
memset(buf, 0, sizeof(buf));
while (fs.getline(buf, 1024, '\n'), !fs.eof())
cout << buf;*/
char ch;
while (fsr.get(ch), !fsr.eof())
fsw.put(ch);
fsw.open("bac.txt", ios::in | ios::out);
#endif
fstream fsread("read.txt", ios::in | ios::out | ios::trunc);
fstream fswrite;
fswrite.open("write.txt", ios::in | ios::out | ios::trunc);
fsread << "hello world" << endl;
fsread << "i like c" << endl;
fsread << "i lile c++" << endl;
fsread << "i like game" << endl;
fsread.seekg(0, ios::beg);
//char buf[1024];
char ch;
while (fsread.get(ch), !fsread.eof())
fswrite << ch;
system("pause");
return 0;
}
两个文本文件:
这样就完全复制到了fswrite打开的文件中。
这里get是一个字符一个字符的复制的,再给一个一行一行的复制:
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
int main() {
#if 0
ifstream fsr("abc.txt");
if (!fsr)
cout << "open error" << endl;
else
cout << "open success" << endl;
ofstream fsw("bca.txt");
if (!fsw)
cout << "open error" << endl;
else
cout << "open success" << endl;
/*char buf[1024];
memset(buf, 0, sizeof(buf));
while (fs.getline(buf, 1024, '\n'), !fs.eof())
cout << buf;*/
char ch;
while (fsr.get(ch), !fsr.eof())
fsw.put(ch);
fsw.open("bac.txt", ios::in | ios::out);
#endif
fstream fsread("read.txt", ios::in | ios::out | ios::trunc);
fstream fswrite;
fswrite.open("write.txt", ios::in | ios::out | ios::trunc);
fsread << "hello world" << endl;
fsread << "i like c" << endl;
fsread << "i lile c++" << endl;
fsread << "i like game" << endl;
fsread.seekg(0, ios::beg);
char buf[1024];
while (fsread.get(buf, 1024, '\n'), !fsread.eof())
fswrite << buf;
system("pause");
return 0;
}
会发现程序一直阻塞:
原因和C++之cin.get中说的get是一样的问题,遇到界定符‘\n’之后,停止流入,并且不会把界定符读入到缓冲区中,在下一次get时,也不会跳过界定符,会再次遇到界定符,这里就要用getline来解决。
3、成员函数getline
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
int main() {
#if 0
ifstream fsr("abc.txt");
if (!fsr)
cout << "open error" << endl;
else
cout << "open success" << endl;
ofstream fsw("bca.txt");
if (!fsw)
cout << "open error" << endl;
else
cout << "open success" << endl;
/*char buf[1024];
memset(buf, 0, sizeof(buf));
while (fs.getline(buf, 1024, '\n'), !fs.eof())
cout << buf;*/
char ch;
while (fsr.get(ch), !fsr.eof())
fsw.put(ch);
fsw.open("bac.txt", ios::in | ios::out);
#endif
fstream fsread("read.txt", ios::in | ios::out | ios::trunc);
fstream fswrite;
fswrite.open("write.txt", ios::in | ios::out | ios::trunc);
fsread << "hello world" << endl;
fsread << "i like c" << endl;
fsread << "i lile c++" << endl;
fsread << "i like game" << endl;
fsread.seekg(0, ios::beg);
char buf[1024];
while (fsread.getline(buf, 1024, '\n'), !fsread.eof())
fswrite << buf << endl;
system("pause");
return 0;
}
这时fswrite打开的文件就完全复制了fsread打开的文件内容:
注意:
由于getline会跳过界定符,所以在往fswrite流对象中写入的时候要自己加上回车符,否则文本都连在一起了,像这样:
这也算是getline的一个小小的缺陷,get(char)可以完美解决,但是如果拷贝大文件的话,效率就太低了,只能说各有优缺点吧。
上面都是单个字符的读写,或者行的读写,最后再来说一下二进制文件的以块为单位的读写:
4、二进制文件的读写
二进制文件的成块读写是通过read和write函数实现的
istream& read(char* buf, int len);
ostream& write(const char* buf, int len);
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
struct Stu {
char name[1024];
char sex;
int age;
};
int main() {
fstream fsb("bi.binary", ios::in | ios::out | ios::trunc | ios::binary);
Stu stu[5] = {
{"郭靖", 'm', 18},
{"黄蓉", 'w', 16},
{"洪七公", 'm', 53},
{"东邪", 'm', 46},
{"梅超风", 'w', 35}
};
for (int i = 0; i < 5; i++) {
fsb.write((char*)&stu[i], sizeof(Stu));
}
fsb.seekg(0, ios::beg);
Stu s;
while (fsb.read((char*)&s, sizeof(s)), !fsb.eof()) {
cout << "name: " << s.name << endl;
cout << "sex: " << s.sex << endl;
cout << "age: " << s.age << endl;
cout << "------------------------------" << endl;
}
system("pause");
return 0;
}
fsb.write((char*)&stu[i], sizeof(Stu));
通过write函数将每个Stu对象写入到fsb打开的文件中去,这里注意必须要进行类型转换,否则报错。
while (fsb.read((char*)&s, sizeof(s)), !fsb.eof())
通过read函数循环读取出fsb打开的文件,同样需要类型转换。
输出结果: