本文主要是介绍(P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 1.文件流
- 2.打开文件
- 3.读写文件
- 4.流状态
- 5.文件关闭
1.文件流
- ofstream,由ostream派生而来,用于写文件
重载了插入运算符<< - ifstream,由istream派生而来,用于读文件
重载了提取运算符>> - fstream,由iostream派生而来,用于读写文件
重载了<<和>>
2.打开文件
- 说明了流对象之后,可使用函数open()打开文件。
文件的打开即是在流与文件之间建立一个连接 - 函数原型
void open (const char* filename, int mode = ios::out, int prot = _SH_DENYNO);参数:
filename:文件的名称,可以包含(绝对和相对)路径
mode:文件打开模式
prot:保护模式
- eg:P59\01.cpp
#include <cassert>
#include <iostream>
#include <fstream>
using namespace std;int main(void)
{//定义一个文件输出流对象ofstream fout;//open的第二和第三参数都有默认值fout.open("test.txt");//这2行等价于下面的1行//ofstream fout;//fout.open("test.txt");ofstream fout("test.txt");//通过构造函数的方式打开//判断打开是否成功或者失败//方法1:判断文件流缓冲区是否处于打开的状态//ofstream文件流对象,子对象:filebufif (fout.is_open()){cout<<"succ"<<endl;}else{cout<<"failed"<<endl;}//方法2:判断文件流状态是否处于正常状态//good方法判断流状态是否正常if (fout.good()) {cout<<"succ"<<endl;}else{cout<<"failed"<<endl;}//方法3:对象作为条件//重载了类型转换运算符void *if (fout) {cout<<"succ"<<endl;}else{cout<<"failed"<<endl;}//方法4,重载!的运算符if (!fout) {cout<<"failed"<<endl;}else{cout<<"succ"<<endl;}//方法5,推荐使用断言的方式判断文件是否打开成功assert(fout);fout.close();return 0;
}
-
测试:在工程目录底下产生了一个文件。.vcproj后缀的目录就是工程目录。
若在这执行,当前目录就是工程目录 -
如果直接运行可执行程序,则当前目录就是可执行文件当前所在的目录
-
if (fout.is_open())的含义
_Filebuffer实际上是_Myfb
_Myfb是basic_filebuf,也就是说:ofstream文件流对象内部有一个子对象:文件流缓冲区_Filebuffer(也就是说ostream类与basic_filebuf类是组合的关系)
-
if (fout) 的含义
F11跟踪进来 ,发现重载了类型转换运算符void *,返回指针
将fout对象转换为void *无类型指针,如果流的状态是失败fail()的状态,则返回空指针,否则成功返回this指针(指向对象自身的指针,肯定不是空指针),也就是说返回的是&fout
-
文件打开模式
其他说明:
(1)ios::out和ios_base::out是一样的。
ios::out实际上是一个枚举,其类型实际上在_Iosb中
ios_base继承至_Iosb,说明out这些枚举量是在_Iosb类中定义的,那么可以它的派生类就可以访问这些枚举常量,ios又继承至ios_base,所以也可以访问这些枚举常量
(2)即使模式是ios::in,打开的时候,肯定会或上一个out模式,写入模式,因为ofstream是用于写入文件的
-
保护模式
(1)_SH_DENYRW,这里的拒绝的含义是:拒绝的是其他进程对文件进行读写
_SH_DENYWR,其他进程可以读,不能写;
_SH_DENYRD,其他进程可以写,但是不能读;
_SH_DENYNO,允许其他进程读取和写入文件,这是默认的保护模式;
_SH_SECURE,允许其他进程读,但是不能写;
一般情况下,不会填写这些参数;
(2)默认值如下:
将该值放到这里,用助手可以go一下,
实际上该值是
继续go一下,保护模式5个值
- 文件打开的几点说明(1)
文件打开也可以通过构造函数打开,eg:ofstream fout(“out.txt”, ios::out);
若构造函数没有接收参数的时候,在构造函数中不会进行任何操作
若构造函数有接收参数的时候,在构造函数中调用open函数
- 文件打开的几点说明(2)
文件的打开方式可以为上述的一个枚举常量,也可以为多个枚举常量构成的按位或表达式 - 文件打开的几点说明(3)
使用open成员函数打开一个文件时,若由字符指针参数所指定的文件不存在,则建立该文件
eg:P59\02.cpp
#include <cassert>
#include <iostream>
#include <fstream>
using namespace std;int main(void)
{//ifstream打开文件,若文件不存在,则不会创建文件ifstream fin("test2.txt");assert(fin);fout.close();return 0;
}
断言失败
-
文件打开的几点说明(4)
当打开方式中不含有ios::ate或者ios::app选项时,则文件指针被自动移动到文件的开始位置,即字节地址为0的位置 -
文件打开的几点说明(5)
从效果上看ofstream指定out模式等同于指定了out和trunc模式 -
文件打开的几点说明(6)
默认情况下,输入输出流fstream对象以in和out模式同时打开 -
文件打开的几点说明(7)
当文件同时以in和out打开时不会清空 -
文件打开的几点说明(8)
如果只使用out模式,而不指定in模式,则文件会清空现有数据 -
文件打开的几点说明(9)
如果同时指定了out与app,不会清空 -
文件打开的几点说明(10)
如果打开文件时指定了trunc模式,则无论是否同时指定了in模式,文件同样会被清空 -
eg:P59\03.cpp
#include <cassert>
#include <iostream>
#include <fstream>
using namespace std;int main(void)
{//文件输出流ofstream默认打开模式是ios::out(没有指任何模式时)//输入流ifstream默认打开模式是ios::inofstream fout("test.txt", ios::out);//等价于指定了ios::out|ios::trunc模式//当文件同时以in和out打开时不会清空ofstream fout("test.txt", ios::out|ios::in);//如果打开文件时指定了trunc模式,则无论是否同时指定了in模式,文件同样会被清空ofstream fout("test.txt", ios::out|ios::in|ios::trunc);//如果同时指定了out与app,不会清空ofstream fout("test.txt", ios::out|ios::in|ios::app);assert(fin);fout.close();return 0;
}
- app与ate的区别:P59\04.cpp
#include <cassert>
#include <iostream>
#include <fstream>
using namespace std;int main(void)
{//差别1//如果同时指定了out与app,不会清空ofstream fout("test.txt", ios::out|ios::in|ios::app);//差别2,文件会被清空ofstream fout("test.txt", ios::out|ios::ate);//文件不会被清空ofstream fout("test.txt", ios::out|ios::in|ios::ate);//往文件里写入一些数据,因为输出流对象重载了<<运算符ofstream fout1("test3.txt", ios::in | ios::out | ios::ate);ofstream fout2("test3.txt", ios::in | ios::out | ios::ate);//追加方式1//结果发现:输出了Y//第一个输出流对象填了一个X,第二个输出流对象填了个Y//所以第二次把前面的X给覆盖了,即:一旦打开文件,文件指针就定位到了文件末尾//ate是打开文件后,立即将文件定位在文件尾fout1 << "X";fout2 << "Y"; //追加方式2//结果发现,输出了XY//在写入的时候定位到末尾,先定位到末尾,写入X,接着再定位到末尾,再写入Y//app是在写之前定位到末尾ofstream fout1("test3.txt", ios::in | ios::out | ios::app);ofstream fout2("test3.txt", ios::in | ios::out | ios::app);fout1 << "X";fout2 << "Y"; fout1.close();fout2.close();// app 与 trunc 不能共存,流状态为failofstream fout3( "test.txt", ios::out | ios::app | ios::trunc);assert(fout3);//会失败// app 和 ate 可以共存,以app为准ofstream fout1( "test3.txt", ios::in | ios::out | ios::app | ios::ate);ofstream fout2( "test3.txt", ios::in | ios::out | ios::app | ios::ate);assert(fout1);assert(fout2);fout1 << "X";fout2 << "Y"; //Y 输出在 X 的后面return 0;
}
- 文件打开模式的有效组合
(1)app与trunc不能同时存在, app 和 ate 可以共存,以app为准
(2)所有的打开模式组合还可以添加ate模式。对这些模式添加ate模只会改变文件打开时的初始定位,将文件定位于文件末尾处。
3.读写文件
- 见上
4.流状态
- 打开文件之后就会设置流状态
- 对应于这个标志字各状态位,ios类还提供了以下成员函数来检测或设置流的状态:
bool rdstate(); //返回流的当前状态标志字
bool eof(); //返回非0值表示到达文件尾
bool fail(); //返回非0值表示操作失败
bool bad(); //返回非0值表示出现错误,物理上产生致命错误
bool good(); //返回非0值表示流操作正常
bool clear(int flag=0); //将流的状态设置为flag,清除流状态,如果流出现失败,但又想继续使用流的话,就先清除
- eg:P59\05.cpp
#include <cassert>
#include <iostream>
#include <fstream>
using namespace std;int main(void)
{// app 与 trunc 不能共存,流状态为failofstream fout3( "test.txt", ios::out | ios::app | ios::trunc);if (fout3.good()){cout << "good" << endl;}if (fout3.bad()){cout << "bad" << endl;}if (fout3.fail()){cout << "fail" << endl;}if (fout3.eof()){cout << "eof" << endl;}//如果出现bad错误,流不能继续使用了//流状态出现错误,但是还想继续使用,需要clearfout3.clear();fout3.open( "test.txt"); // clear之后能够重新openif (fout3){cout << "open succ" << endl;}elsecout << "open failed" << endl;fout3.close();return 0;
}
5.文件关闭
- 每个文件流类中都提供有一个关闭文件的成员函数close()
功能:当打开的文件操作结束后,就需要关闭它,使文件流与对应的物理文件断开联系,并能够保证最后输出到文件缓冲区中的内容,无论是否已满,都将立即写入到对应的物理文件中(磁盘上)
函数原型:void close();
-
文件流对应的文件被关闭后,还可以利用该文件流调用open成员函数打开其他的文件,最好先clear 一下。
-
参考:从零开始学C++之IO流类库(二):文件流(fstream, ifstream, ofstream)的打开关闭、流状态,从零开始学C++之IO流类库(二):文件流(fstream, ifstream, ofstream)的打开关闭、流状态
这篇关于(P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!