从零开始学C++之IO流类库(二):文件流(fstream, ifstream, ofstream)的打开关闭、流状态

一、文件流

ofstream,由ostream派生而来,用于写文件 ifstream,由istream派生而来, 用于读文件 fstream,由iostream派生而来,用于读写文件

二、打开文件

说明了流对象之后,可使用函数open()打开文件。文件的打开即是在流与文件之间建立一个连接 函数原型

void open(const char * filename, int mode = ios::out,int prot = _SH_DENYNO);

参数 filename:文件的名称,可以包含(绝对和相对)路径 mode:文件打开模式 prot:保护模式

(一)、文件打开模式

打开方式 描述

ios::in 打开一个供读取的文件(ifstream流的默认值)

ios::out 打开一个供写入的文件(ofstream流的默认值) ios::app 在写之前找到文件尾 ios::ate 打开文件后立即将文件定位在文件尾 ios::trunc 废弃当前文件内容 ios::nocreate(已不再支持) 如果要打开的文件并不存在,那么以此参数调用open()函数将无法进行 ios::noreplace (已不再支持) 如果要打开的文件已存在,试图用open()函数打开时将返回一个错误。 ios::binary 以二进制的形式打开一个文件,默认为文本文件

(二)、保护模式

#define _SH_DENYRW      0x10    /* deny read/write mode */拒绝对文件进行读写 #define _SH_DENYWR      0x20    /* deny write mode */拒绝写入文件 #define _SH_DENYRD      0x30    /* deny read mode */拒绝文件的读取权限 #define _SH_DENYNO      0x40    /* deny none mode */读取和写入许可 #define _SH_SECURE      0x80    /* secure mode */共享读取,独占写入

注意:假设A进程以_SH_DENYRW 打开,那么是B进程不能再对文件进行读写。

(三)、文件打开模式的有效组合

上述所有的打开模式组合还可以添加ate模式。对这些模式添加ate模只会改变文件打开时的初始定位,在第一次读或 写之前,将文件定位于文件末尾处。

(四)、文件打开的几点说明

1、文件打开也可以通过构造函数打开,例如:ofstream fout(“out.txt“,ios::out);

2、文件的打开方式可以为上述的一个枚举常量,也可以为多个枚举常量构成的按位或表达式。 3、使用open成员函数打开一个文件时,若由字符指针参数所指定的文件不存在,则建立该文件。(out) 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模式,文件同样会被清空

三、流状态

对应于这个标志字各状态位,ios类还提供了以下成员函数来检测或设置流的状态:

bool rdstate();             //返回流的当前状态标志字 bool eof();                 //返回非0值表示到达文件尾 bool fail();               //返回非0值表示操作失败 bool bad();                 //返回非0值表示出现错误 bool good();               //返回非0值表示流操作正常 bool clear(int flag=0); //将流的状态设置为flag

为提高程序的可靠性,应在程序中检测I/O流的操作是否正常。当检测到流操作出现错误时,可以通过异常处理来解决问题。

四、文件的关闭

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

函数原型:void close();

文件流对应的文件被关闭后,还可以利用该文件流调用open成员函数打开其他的文件,最好先clear 一下。

#include <cassert>
#include <iostream>
#include <fstream>

using namespace std;

int main(void)
{
    /******************************************************/
    //若不存在文件,会创建文件
    //ofstream fout;
    //fout.open("test.txt");
    ofstream fout("test.txt", ios::out | ios::app);

    //判断流状态
    //if (fout.is_open())
    //{
    //  cout<<"succ"<<endl;
    //}
    //else
    //  cout<<"failed"<<endl;

    //if (fout.good())
    //{
    //  cout<<"succ"<<endl;
    //}
    //else
    //  cout<<"failed"<<endl;

    //if (fout)
    //{
    //  cout<<"succ"<<endl;
    //}
    //else
    //  cout<<"failed"<<endl;

    //if (!fout)
    //{
    //  cout<<"failed"<<endl;
    //}
    //else
    //  cout<<"succ"<<endl;

    assert(fout);
    fout.close();

    /************************************************************/
    // 若文件不存在,不会创建文件
    ifstream fin("test2.txt");

    //  assert(fin); //文件不存在,断言失败

    fin.close();
    /**********************************************************/
    //ofstream fout1("test3.txt", ios::in | ios::out | ios::ate);
    //ofstream fout2("test3.txt", ios::in | ios::out | ios::ate);

    //ofstream fout1("test3.txt", ios::in | ios::out | ios::app);
    //ofstream fout2("test3.txt", ios::in | ios::out | ios::app);

    // 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 的后面

    fout1.close();
    fout2.close();
    /****************************************************************/

    // 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;
    }

    fout3.clear();
    fout3.open("test.txt"); // clear之后能够重新open
    if (fout3)
    {
        cout << "open succ" << endl;
    }
    else
        cout << "open failed" << endl;

    fout3.close();

    return 0;
}

参考:

C++ primer 第四版 Effective C++ 3rd C++编程规范

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏coder修行路

多进程、协程、事件驱动及select poll epoll

多线程的使用场景 IO操作不占用CPU 计算占用cpu python多线程不适合cpu密集型操作的任务,适合IO操作密集型的任务 多进程 简单的一个多进程例子:...

3149
来自专栏coding

Linux笔记2

1432
来自专栏瓜大三哥

UVM(十)之config机制续2

UVM(十)之config机制续2 1.用专门的类来组织config变量 到这里为止,本章目前所设计的都是少量数据在不同的component之间的传递,对于一...

2339
来自专栏吴柯的运维笔记

【Linux环境下】绝对要掌握的创建/查看指令

mkdir mkdir [-p] A/B/C 递归创建(带父目录) mkdir A 在当前路径下创建的A文件夹 tree:以目录树的方式显示文件夹结构 cat...

3348
来自专栏转载gongluck的CSDN博客

UNPv13:#第1章#简介

概述 ? TCP本身并不提供记录结束标志:如果应用程序需要确定记录的边界,它就要自己去实现,已有一些常用的方法可供选择。从TCP套接字读取数据时,我们总...

3089
来自专栏乐百川的学习频道

Python学习笔记 模块介绍

模块 导入模块 Python官方教程让我们在Python解释器中练习。但是当我们结束解释器,所有的代码都消失了。如果我们希望让代码永久保存的话,就需要将它们保存...

1806
来自专栏Java技术分享

Ajax请求中给全局变量赋值的解决方案

昨天PP遇到一个问题,ajax修改全局变量后,外面获取不到ajax里赋的值,结果为空 问题代码如下图: ? 输出结果如下图: ? 原因: 先在控制台看看是a...

1977
来自专栏决胜机器学习

《Redis设计与实现》读书笔记(十二) ——Redis键的生存时间与过期时间

《Redis设计与实现》读书笔记(十二) ——Redis键的生存时间与过期时间 (原创内容,转载请注明来源,谢谢) 1、设置方式 在redis客户端,可以通过e...

2704
来自专栏程序员互动联盟

【专业技术第七讲】linux下如何编译C语言?

存在问题: 小伙伴们都知道gcc -c -o 但是其中的过程和一些参数就不是太清楚了,往往编译出错不知道咋办? 解决方案: 我们来简单普及一下,让大家不盲从请...

3405
来自专栏nummy

ipython 自动加载 auto_reload 扩展

在开发中django或者flask开发中,调试的时候经常用到manager shell.如果安装了ipython的话,默认是打开ipython的。在调试过程中,...

843

扫码关注云+社区