6

我在编写读取 apache 日志的 Linux 控制台应用程序时遇到了一些麻烦。

我需要处理 bash 脚本参数,最后一个是日志文件的路径。我的问题是,如果文件不存在,我想抛出一个异常。

但是当我尝试以只读模式打开文件时,它会创建文件而不是失败!

这是代码:

// logreader.h

#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <stdexcept>


class LogReader
{
    public:
        LogReader(int, const char **);
        virtual ~LogReader();

        // ...

    private:
        std::ifstream log_;
};

// logreader.cpp

#include <logreader.h>

LogReader::LogReader(int argc, const char ** argv):
    log_()
{
    log_.exceptions(std::ifstream::failbit | std::ifstream::badbit);
    for (int i = 1; i < argc; ++i)
    {
        std::string arg(argv[i]);
        if (i == argc - 1)
        {
            try
            {
                log_.open(arg.c_str(), std::ifstream::in);
            }
            catch (std::ifstream::failure)
            {
                throw std::runtime_error("The file " + arg + " wasn't opened");
            }
        }
    }
}

LogReader::~LogReader()
{
}

// main.cpp

#include <logreader.h>

int main(int argc, const char ** argv)
{
    LogReader(argc, argv);
    return 0;
}

脚本调用:

jmcomets $ ./test -g -l
jmcomets $ ls -l
-rw-rw-r-- 1 jmcomets jmcomets     0 Nov 14 22:41 -l 
4

4 回答 4

3

由于您正在打开一个std::ifstream,因此有必要根据 27.9.1.9 [ifstream.members] 第 4 段添加std::ios_base::in(或任何其他拼写):该标志是通过调用自动添加的。请注意,an或 an会自动添加(27.9.1.13 [ofstream.members] paragrpah 3) 或(27.9.1.17 [fstream.members] 第 3 段),如果新文件不存在,这两者都会导致创建新文件(并且有写权限等)。std::ios_base::openmodeopen()std::ofstreamstd::fstreamstd::ios_base::outstd::ios_base::in | std::ios_base::out

如果您发布的代码创建了一个新文件,则标准 C++ 库的实现是错误的:当仅指定标志时,使用带有(27.9.1.4 [filebuf.members] 段落std::ios_base::in的打开模式“好像”打开文件5)。反过来,当它获得(7.21.5.3 第 3 段)的打开模式时,它不会创建新文件。"r"fopen()fopen()"r"

于 2012-11-14T22:27:28.330 回答
2

您可以failbit在异常标志中设置ifstream

std::ifstream log;
log.exceptions ( std::ifstream::failbit );
try {
    log.open ("test.txt");
}
catch (std::ifstream::failure e) {
    std::cout << "Exception opening/reading file\n";
}

来源

我已经测试过,如果文件无法打开,ifstream会抛出异常,例如找不到文件,没有读取权限。failure它将只读方式打开。

于 2012-11-14T21:27:52.160 回答
0

使用与 Linux 兼容的东西进行编辑;

在写之前尝试用 fopen 打开。如果文件 DNEFILE指针将为空。

FILE * file;
file = fopen ("myfile.txt","r");

if (file == NULL)
   //throw if fopen didn't already.
else
    //do stuff with my file
于 2012-11-14T21:26:45.290 回答
0

您需要将 ifstream::in 作为第二个参数指定为:

log.open(arg.c_str(), ifstream::in)

你也可以这样做:

std::ifstream log(arg.c_str(), ifstream::in);

并跳过调用open()

于 2012-11-14T21:30:25.853 回答