c++文件流打开模式与is_open方法

检测流状态的方法

在c++中经常需要读写文件,在打开文件进行操作之前,我们需要确保流的打开状态正常。

可以通过以下方法判断流状态正常:

#include <fstream>

ifstream fin;
fin.open("demo.txt");
// 1st attempt
if (fin.fail()) {} // open failed
// 2nd attempt
if (!fin) {} // open failed
// 3rd attempt
if (!fin.good()) {} // open failed
// 4th attempt
if (!fin.is_open()) {} // open failed

这些方法都是可以的,但是强烈建议使用第4种方法is_open。

因为它能检测出其他方式不能检测到的微妙问题。
——引自《c++ primer plus》

文件打开模式

由于这个微妙问题与文件模式有关,所以在此先做介绍。

文件模式描述的是文件将如何被使用:读、写、追加、二进制方式等。

将流与文件关联时,都可以提供指定文件打开模式的第二个参数:

ifstream fin("bar", mode);// mode指定的模式

c++提供的文件模式如下:

常量含义
ios_base::in以读模式打开文件
ios_base::out以写模式打开文件
ios_base::ate打开文件,并移动到文件尾
ios_base::app追加到文件尾
ios_base::trune如果文件存在,则截短文件
ios_base::binary二进制文件

比如,以追加方式写文件时:

ofstream fout("bar", ios_base::out | ios_base::app);

由于历史原因,c++中经常会有c的代码,或者c++使用c编写的库,所以需要清楚 c++ 与 c 打开模式的对应关系:

c++模式c模式含义
ios_base::in“r”以读模式打开文件
ios_base::out“w”以写模式打开文件,如果文件已存在,则截短文件,同 “ios_base::out | ios_base::trune”
ios_base::out | ios_base::app“a”追加写
ios_base::in | ios_base::out“r+”以读写模式打开,在文件允许位置写入
ios_base::in | ios_base::out | ios_base::trune“w+”以读写模式打开,如果文件已存在,则截短文件
c++mode | ios_base::binarycmode+b以二进制模式打开文件
c++mode | ios_base::atecmode以指定模式打开文件,并移动到文件尾。c中使用独立的函数调用移动到文件尾:fseek(file, 0, SEEK_END)

注意:ios_base::ate 和 ios_base::app
都将文件指针指向文件尾,二者的区别是ios_base::app只允许将数据添加到文件尾,而ios_base::ate将指针放到文件尾。

为什么使用is_open

其实,在上述四种方法中,前三种测试方法是等价的。

但是,它们无法检测出这样的情况: 以不合适的文件模式打开时导致的失败。

比如,当尝试以ios_base::in | ios_base::trune模式打开文件时,这就是不允许的模式组合,导致打开流失败。

is_open()方法用于检测此种故障。

以上是书上的说法,笔者感觉好奇,当以这种模式打开文件时,会出现怎样的错误情况,于是随手写了个测试程序:

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    ifstream fin("d.txt", ios_base::in | ios_base::trunc);
    if (!fin.good() || !fin || fin.fail())
    {
        cout << "the 3 ways think open file failed\n";
        return 1;
    }
    cout << "the 3 ways don't think open file failed\n";

    if (!fin.is_open())
    {
        cout << "is_open think open file failed\n";
        return 2;
    }
    cout << "the 4th way don't think open file failed\n";

    char ch;
    while (fin.get(ch))
        cout << ch;
    cout << endl;

    fin.clear();
    fin.close();

    return 0;
}

编译测试:

# 先不创建d.txt文件
% ./a.out 
the 3 ways think open file failed

% touch d.txt && echo a > d.txt
% ./a.out 
the 3 ways think open file failed

由此可见,前三种方式也能检测到此种故障。

小结

is_open()是较新的c++引入的方法,它的引入肯定是存在理由的。

上述示例虽然在我的电脑上运行通过,但在其他系统上可能会如书中讲解一致。

总之,既然使用is_open方法没有副作用,只是多写了几个字符,这样能避免某些隐匿的bug,还是非常值得的。

  • 24
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
`finfo_open`函数用于创建一个新的文件信息资源对象,以便后续使用`finfo_file`或`finfo_buffer`函数获取文件或数据的MIME类型和其他相关信息。 函数原型如下: ```php resource finfo_open ([ int $options = FILEINFO_NONE [, string $magic_file = NULL ]] ) ``` 函数参数说明: - `options`:可选参数,指定文件信息数据库的搜索选项,可以是以下值之一或它们的按位或组合: - `FILEINFO_NONE`:默认值,不进行任何搜索。 - `FILEINFO_SYMLINK`:对符号链接进行搜索。 - `FILEINFO_MIME_TYPE`:返回MIME类型字符串。 - `FILEINFO_MIME_ENCODING`:返回MIME编码字符串。 - `FILEINFO_MIME`:返回MIME类型和编码字符串。 - `FILEINFO_CONTINUE`:返回所有可能的匹配结果,而不是仅返回第一个匹配结果。 - `FILEINFO_PRESERVE_ATIME`:保留文件的访问时间。 - `FILEINFO_RAW`:返回未经处理的原始MIME类型字符串。 - `magic_file`:可选参数,指定文件信息数据库文件的路径,如果未指定,则使用系统默认的文件信息数据库。 函数返回值为一个文件信息资源对象,如果创建失败则返回`false`。 使用示例: ```php $finfo = finfo_open(FILEINFO_MIME_TYPE); if (!$finfo) { die('Failed to create fileinfo object'); } $filename = 'example.jpg'; $mime_type = finfo_file($finfo, $filename); echo "The MIME type of $filename is: $mime_type"; finfo_close($finfo); //释放资源 ``` 以上示例创建了一个文件信息资源对象`$finfo`,并使用`finfo_file`函数获取了`example.jpg`文件的MIME类型,并将结果打印输出。最后使用`finfo_close`函数释放资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值