我在编写一个读取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
答案 0 :(得分:3)
由于您要打开std::ifstream
,因此需要根据27.9.1.9 [ifstream.members]第4段添加std::ios_base::in
(或std::ios_base::openmode
的任何其他拼写):通过调用open()
自动添加标记。请注意,std::ofstream
或std::fstream
会自动添加std::ios_base::out
(27.9.1.13 [ofstream.members] paragrpah 3)或std::ios_base::in | std::ios_base::out
(27.9.1.17 [fstream.members]第3段),如果新文件不存在(并且有写权限等),这两个文件都会被创建。
如果您发布的代码创建了一个新文件,那么标准C ++库的实现是错误的:当只指定了标志std::ios_base::in
时,该文件是打开的&#34;好像&#34;使用开放模式"r"
和fopen()
(27.9.1.4 [filebuf.members]第5段)。 fopen()
在"r"
开放模式(7.21.5.3第3段)时,不会创建新文件。
答案 1 :(得分:1)
您可以在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
例外,例如找不到文件,没有读取权限。 将以只读方式打开。
答案 2 :(得分:0)
使用Linux兼容的东西编辑;
在写作之前尝试使用fopen打开。如果文件DNE FILE
指针将为空。
FILE * file;
file = fopen ("myfile.txt","r");
if (file == NULL)
//throw if fopen didn't already.
else
//do stuff with my file
答案 3 :(得分:0)
您需要将ifstream :: in指定为第二个参数:
log.open(arg.c_str(), ifstream::in)
你也可以这样做:
std::ifstream log(arg.c_str(), ifstream::in);
并跳过对open()