1.文件打开
-
已创建的文件流对象需要和指定的磁盘文件建立关联, 以便使文件流流向指定的磁盘文件, 这个过程称为文件打开。
-
打开文件有两种方式:
(1) 是定义文件流对象时使用带参数的构造函数;
(2) 是调用文件流成员函数open。 -
文件流操作的函数如下:
►输入: 读操作, 将文件中的内容读到内存中。
►输出: 写操作, 将内存中的数据写到文件中。
ifstream(); //文件输入流构造函数
//文件输入流构造函数, 用指定的mode方式打开filename文件
ifstream(const char* filename,ios_base::openmode mode=ios_base::in);
ofstream(); //文件输出流构造函数
//文件输出流构造函数, 用指定的mode方式打开filename文件
ofstream(const char* filename,ios_base::openmode mode=ios_base::out);
fstream(); //文件输入输出流构造函数
//文件输入输出流构造函数, 用指定的mode方式打开filename文件
fstream(const char* filename,ios_base::openmode mode=ios_base::in|ios_base::out);
//用指定的mode方式打开filename文件
void open(const char* filename,ios_base::openmode mode=ios_base::in);
bool operator!(); //检测流对象是否为空
bool is_open(); //检测文件是否打开
- 打开方式openmode
- 打开方式openmode的说明如下
(1) 可以用位或运算(|) 对openmode进行组合。
(2) 打开文件时操作可能会失败, 如果打开操作失败, open函数返回值为0(假) 。
如果是调用构造函数打开文件且打开操作失败,则流对象的值为0(空对象) 。
可以据此测试打开是否成功, 确定能否对该文件继续操作。
(3) 每一个打开的文件都有一个文件指针, 该指针初始位置要么在文件末尾(当指定ios_base::app或ios_base::ate时) , 要么在文件开头。
每次读写都从文件指针的当前位置开始。
每读写一个字节,指针就自动后移一个字节。
当文件指针移到最后, 就会遇到文件结束EOF(文件结束符) 。
2.文件关闭
- 当不再使用文件时, 应该关闭该文件。 关闭文件可以调用文件流成员函数:
void close(); //关闭文件
- 当文件关闭后, 就不能再通过流对象对文件进行操作了, 除非再次打开。
3.文件状态
- 文件流提供如下四个成员函数用来检测文件状态:
bool eof(); bool bad();
bool fail(); bool good();
(1)bool eof();
如果文件已到末尾, eof函数返回真(1) , 否则返回假(0) 。
(2)bool bad();bool fail();
如果在读写文件过程中出错, bad函数返回true。
如对一个不是为写状态打开的文件进行写入, 或者要写入的设备没有剩余空间,
除了与bad函数同样的情况下会返回true以外, 格式错误时fail函数也会返回true。
格式错误指的是:如要读入一个整数而得到一个字母时。
- 如果调用以上任何一个函数返回true的话, good函数函数返回false。
若都返回true,前三个函数表示文件有问题;
good函数:文件是否良好,良好返回true,不良好,返回false
4.文件操作的基本形式
-
几乎所有文件应用中的打开和关闭的程序形式是相同的, 为此给出通用的文件打开和关闭的操作步骤:
①定义文件流对象;
②通过构造函数或者成员函数open打开文件(或创建文件) ;即:将流对象与某个文件关联起来
③打开文件失败时中断文件处理;
④对文件进行各种操作;
⑤文件处理结束时关闭文件。 -
文件操作的基本形式 —代码形式
ifstream infile(文件名,openmode); //打开文件或创建文件,第1第2步
if (!infile) //打开或创建成功继续操作,第3步
{
…//文件读写操作
infile.close(); //处理结束时关闭文件
}
或:
ifstream infile;定义文件流对象
infile.open("文件名",openmode); //打开文件或创建文件,调用成员函数open将文件流对象与某个文件关联起来
if (!infile.fail()) //打开或创建成功继续操作
{
…//文件读写操作
infile.close(); //处理结束时关闭文件
}
- 文件操作包括读写和定位, 除流提取和流插入运算符外,
文件流还有如下有用的操作文件的成员函数:
//用于文件输入流
istream& read(char* s,streamsize n); //从文件中读n个字节到s,s为字符数组名
streampos tellg(); //返回文件指针的位置
istream& seekg(streampos pos);//移动文件指针到pos位置
istream& seekg(streamoff off,ios_base::seekdir dir);//以dir参照off偏移移动文件指针,
dir表示:从哪开始移动,off表示:移动多少字节
//用于文件输出流
ostream& write(const char* s,streamsize n); //输出s的n个字节到文件
streampos tellp(); //返回文件指针的位置
ostream& seekp(streampos pos); //移动文件指针到pos位置
ostream& seekp(streamoff off,ios_base::seekdir dir);//以dir参照off偏移移动文件指针
flush(); //文件输出流刷新
5.文件操作举例
-
(1) 对ASCII文件操作。
对ASCII文件的读写操作可以用以下两种方法:
①用流插入(<<) 运算符和流提取(>>) 运算符输入输出标准类型的数据;
②用流对象成员函数get、 getline、 put等进行字符的输人输出。 -
eg:将源文件每行文本添加一个行号输出到目的文件中。
#include <fstream> //使用文件流
#include <iomanip>
using namespace std; //文件流定义在std命名空间
int main()
{
char s1[500]; int cnt=0;//cnt表示行号
ifstream inf("a.cpp"); //打开源文件读,定义了一个输入文件流对象
if (!inf.fail()) //没有错误
{
ofstream outf("b.cpp"); //创建目的文件写
while (!inf.eof()) //是否到源文件末尾:a.cpp文件,因为inf对象与a.cpp文件相关联
{
//getline是获得一行文本,将a.cpp文件的一行文本放到s1的字符数组里面
inf.getline(s1,sizeof(s1)-1); //读源文件字符串,为啥-1:字符串结束标志,将字符串放到字符数组
//将字符串添加行号输出到目的文件
//输出到b.cpp里面了,输出文件流对象与b.cpp相关链
//setfill('0'):站不满,用0补空格
//setw(4):输出宽度
outf<<setfill('0')<<setw(4)<<++cnt<<" "<<s1<<endl; //cnt:以0001的方式输出
}
outf.close(); //关闭目的文件
inf.close(); //关闭源文件
}
return 0;
}