Как лучше всего проверить, существует ли файл на C ++? (кросс-платформенный)

97

Я прочитал ответы на вопрос , как лучше всего проверить, существует ли файл на C? (кросс-платформенный) , но мне интересно, есть ли лучший способ сделать это, используя стандартные библиотеки C ++? Желательно вообще без попытки открыть файл.

Оба statи accessв значительной степени не могут быть Google. Что мне #includeследует использовать?

c0m4
источник
<io.h> для доступа (который на самом деле может быть _access).
Роб
Да, как оттуда указано.
c0m4 06

Ответы:

170

Используйте boost :: filesystem :

#include <boost/filesystem.hpp>

if ( !boost::filesystem::exists( "myfile.txt" ) )
{
  std::cout << "Can't find my file!" << std::endl;
}
Андреас Магнуссон
источник
68
Кажется, немного хлопотно установить огромную стороннюю библиотеку, чтобы сделать что-то, что должно быть простым
c0m4
89
Boost - это библиотека, в которой разрабатывается большая часть того, что в конечном итоге станет частью стандартной библиотеки C ++. Многие из тех, кто занимается Boost, связаны со стандартом C ++. Таким образом , повышение не только какая - либо библиотеки третьей стороны. Если вы программируете на C ++, у вас должен быть установлен boost!
Андреас Магнуссон
Мне кажется, я припоминаю, что b :: fs :: exists возвращает "true" для несуществующих файлов в сетевых папках: "\\ machine \ share \ this_file_doesnt_exist" => true. Последний раз я проверял, был на
Boost
Если ваш компилятор поставляется с реализацией tr1, вам даже не нужно устанавливать Boost. Он будет в файловой системе std :: tr1 ::
Неманья Трифунович
1
На самом деле ASFAIK не попал в TR1, но будет добавлен на более позднем этапе. Я также не нашел никаких ссылок на него в официальном черновике TR1: open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
Андреас Магнуссон
41

Будьте осторожны с условиями гонки: если файл исчезнет между проверкой «существует» и временем, когда вы его откроете, ваша программа неожиданно завершится ошибкой.

Лучше пойти и открыть файл, проверить на сбой и, если все в порядке, что-то сделать с файлом. Это еще более важно для критически важного для безопасности кода.

Подробная информация о безопасности и условиях гонки: http://www.ibm.com/developerworks/library/l-sprace.html.

rlerallut
источник
30

Я счастливый пользователь буста и обязательно воспользуюсь решением Андреаса. Но если у вас не было доступа к библиотекам повышения, вы можете использовать библиотеку потоков:

ifstream file(argv[1]);
if (!file)
{
    // Can't open file
}

Это не так хорошо, как boost :: filesystem :: exists, поскольку файл действительно будет открыт ... но тогда это обычно следующее, что вы хотите сделать в любом случае.

MattyT
источник
15
Но с помощью этого кода вы также можете перейти к предложению if, если у вас нет разрешений для файла, хотя он существует. В большинстве случаев это не имеет значения, но все же стоит упомянуть.
scigor
1
Замечено , что хорошо () дает также верно , если данный аргумент обозначает каталог, см stackoverflow.com/questions/9591036/...
FelixJongleur42
12

Используйте stat (), если он достаточно кроссплатформенный для ваших нужд. Но это не стандарт C ++, а POSIX.

В MS Windows есть _stat, _stat64, _stati64, _wstat, _wstat64, _wstati64.

activout.se
источник
1
<sys / types.h> и <sys / stat.h> См. msdn.microsoft.com/en-us/library/14h5k7ff(VS.71).aspx
activout.se
1
Хороший ответ +1 за НЕ ИСПОЛЬЗУЙТЕ УСИЛЕНИЕ , поскольку это перебор, однако написать это из того, что здесь предоставлено, было нетривиально, поэтому я просто опубликовал ответ. Проверьте пожалуйста.
gsamaras
9

Как насчет access?

#include <io.h>

if (_access(filename, 0) == -1)
{
    // File does not exist
}
Роб
источник
Нормально ли io.h доступен в Windows и Linux, даже если он не является стандартным?
c0m4
1
access () - это функция POSIX, доступная через <unistd.h> в Linux.
Alex B
9

Другая возможность заключается в использовании good()функции в потоке:

#include <fstream>     
bool checkExistence(const char* filename)
{
     ifstream Infield(filename);
     return Infield.good();
}
Самер
источник
7

Я бы пересмотрел попытку выяснить, существует ли файл. Вместо этого вы должны попытаться открыть его (в стандартном C или C ++) в том же режиме, в котором вы собираетесь его использовать. Какой смысл знать, что файл существует, если, скажем, он не доступен для записи, когда вам нужно его использовать?

шипучка
источник
Что делать, если вы пишете lsпрограмму, похожую на -подобную? Я предполагаю, что исходный плакат здесь вообще не хочет открывать файл. Функция Posix stat должна давать вам информацию о правах доступа к файлу, поэтому она решит эту проблему.
Michael
6

Если ваш компилятор поддерживает C ++ 17, вам не нужно ускорение, вы можете просто использовать std::filesystem::exists

#include <iostream> // only for std::cout
#include <filesystem>

if (!std::filesystem::exists("myfile.txt"))
{
    std::cout << "File not found!" << std::endl;
}
AlbertM
источник
3

Нет ТРЕБУЕТСЯ , что было бы излишним .


Используйте stat () (не кроссплатформенный, хотя, как упоминалось Павоном), например:

#include <sys/stat.h>
#include <iostream>

// true if file exists
bool fileExists(const std::string& file) {
    struct stat buf;
    return (stat(file.c_str(), &buf) == 0);
}

int main() {
    if(!fileExists("test.txt")) {
        std::cerr << "test.txt doesn't exist, exiting...\n";
        return -1;
    }
    return 0;
}

Вывод:

C02QT2UBFVH6-lm:~ gsamaras$ ls test.txt
ls: test.txt: No such file or directory
C02QT2UBFVH6-lm:~ gsamaras$ g++ -Wall main.cpp
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
test.txt doesn't exist, exiting...

Другую версию (и ту) можно найти здесь .

гсамарас
источник
Не тот, кто проголосовал против, но вопрос, заданный для кроссплатформенного решения, а статистика существует не на всех платформах.
pavon
0

Если вы уже используете класс потока входного файла ( ifstream), вы можете использовать его функцию fail().

Пример:

ifstream myFile;

myFile.open("file.txt");

// Check for errors
if (myFile.fail()) {
    cerr << "Error: File could not be found";
    exit(1);
}
Реза Саадати
источник