У меня возникли проблемы с написанием консольного приложения для Linux, которое читает журналы apache.
Мне нужно обработать аргументы 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
Вы можете установить 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
исключение, если файл не может быть открыт, например, файл не найден, нет прав на чтение. Это будут открыт только для чтения.
Так как вы открываете std::ifstream
надо добавить std::ios_base::in
(или любое другое написание std::ios_base::openmode
) в соответствии с пунктом 27.9.1.9 [ifstream.members]: флаг добавляется автоматически при вызове 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
указан, файл открывается «как будто» в открытом режиме "r"
с fopen()
(27.9.1.4 [filebuf.members] пункт 5). fopen()
в свою очередь не создает новый файл, когда он получает открытый режим "r"
(7.21.5.3 пункт 3).
Вам нужно указать ifstream :: in в качестве второго параметра как:
log.open(arg.c_str(), ifstream::in)
Вы также можете сделать:
std::ifstream log(arg.c_str(), ifstream::in);
и пропустить звонок open()
Редактировать с помощью чего-нибудь совместимого с 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