0
点赞
收藏
分享

微信扫一扫

(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文件流对象,子对象:filebuf
if (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())的含义
  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_#include


  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_文件流_02

  • _Filebuffer实际上是_Myfb
  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_ios_03

  • _Myfb是basic_filebuf,也就是说:ofstream文件流对象内部有一个子对象:文件流缓冲区_Filebuffer(也就是说ostream类与basic_filebuf类是组合的关系)
  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_ios_04

  • if (fout) 的含义
  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_ios_05

  • F11跟踪进来 ,发现重载了类型转换运算符void *,返回指针
    将fout对象转换为void *无类型指针,如果流的状态是失败fail()的状态,则返回空指针,否则成功返回this指针(指向对象自身的指针,肯定不是空指针),也就是说返回的是&fout
  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_文件流_06

  • 文件打开模式
  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_#include_07

  • 其他说明:
    (1)ios::out和ios_base::out是一样的。
  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_文件流_08

  • ios::out实际上是一个枚举,其类型实际上在_Iosb中
  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_文件流_09

  • ios_base继承至_Iosb,说明out这些枚举量是在_Iosb类中定义的,那么可以它的派生类就可以访问这些枚举常量,ios又继承至ios_base,所以也可以访问这些枚举常量
  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_#include_10


  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_ios_11

  • (2)即使模式是ios::in,打开的时候,肯定会或上一个out模式,写入模式,因为ofstream是用于写入文件的
  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_文件流_12


  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_文件流_13

  • 保护模式
  • (P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_#include_14

(1)_SH_DENYRW,这里的拒绝的含义是:拒绝的是其他进程对文件进行读写

_SH_DENYWR,其他进程可以读,不能写;

_SH_DENYRD,其他进程可以写,但是不能读;

_SH_DENYNO,允许其他进程读取和写入文件,这是默认的保护模式;

_SH_SECURE,允许其他进程读,但是不能写;

一般情况下,不会填写这些参数;

(2)默认值如下:

(P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_文件流_15


将该值放到这里,用助手可以go一下,

(P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_#include_16


实际上该值是

(P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_文件流_17


继续go一下,保护模式5个值

(P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_ios_18

  • 文件打开的几点说明(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;
}

断言失败

(P59)io流类库:文件流,打开文件,读写文件,流状态,文件关闭_#include_19

  • 文件打开的几点说明(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::in
ofstream 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 不能共存,流状态为fail
ofstream 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 不能共存,流状态为fail
ofstream 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错误,流不能继续使用了
//流状态出现错误,但是还想继续使用,需要clear
fout3.clear();
fout3.open( "test.txt"); // clear之后能够重新open
if (fout3)
{
cout << "open succ" << endl;
}
else
cout << "open failed" << endl;

fout3.close();

return 0;
}

5.文件关闭

  • 每个文件流类中都提供有一个关闭文件的成员函数close()
    功能:当打开的文件操作结束后,就需要关闭它,使文件流与对应的物理文件断开联系,并能够保证最后输出到文件缓冲区中的内容,无论是否已满,都将立即写入到对应的物理文件中(磁盘上)

函数原型:void close();

  • 文件流对应的文件被关闭后,还可以利用该文件流调用open成员函数打开其他的文件,最好先clear 一下。
  • 参考:从零开始学C++之IO流类库(二):文件流(fstream, ifstream, ofstream)的打开关闭、流状态,从零开始学C++之IO流类库(二):文件流(fstream, ifstream, ofstream)的打开关闭、流状态


举报

相关推荐

0 条评论