Який найкращий спосіб перевірити, чи існує файл у C ++? (крос-платформа)


97

Я прочитав відповіді на запитання: Який найкращий спосіб перевірити, чи існує файл у C? (крос-платформа) , але мені цікаво, чи є кращий спосіб зробити це, використовуючи стандартні бібліотеки c ++? Бажано, взагалі не намагаючись відкрити файл.

І те, statі accessінше, в основному не піддається керуванню. Що я #includeповинен використовувати?


<io.h> для доступу (який насправді може бути _access).
Роб

Так, як звідти вказували.
c0m4

Відповіді:


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 ++, розробляється. Багато людей, які беруть участь у підвищенні, є людьми, які займаються стандартом C ++. Тож підсилення - це не просто будь-яка стороння бібліотека. Якщо ви програмуєте на C ++, у вас повинно бути встановлено підвищення!
Андреас Магнуссон,

Здається, я згадую, що b :: fs :: существує повертає "true" для неіснуючих файлів на спільних мережевих ресурсах: "\\ machine \ share \ this_file_doesnt_exist" => true. Останній раз, коли я перевіряв, було на посиленні 1.33, будьте обережні ...
rlerallut

Якщо ваш компілятор постачається з реалізацією tr1, вам навіть не потрібно встановлювати Boost. Це буде у файловій системі std :: tr1 ::
Неманья Трифунович

1
Насправді ASFAIK не склав TR1, але буде доданий на більш пізньому етапі. Я також не знайшов жодних посилань на це в офіційному проекті TR1: open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
Andreas Magnusson

41

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

Краще піти і відкрити файл, перевірити на помилку, і якщо все добре, то зробіть щось з файлом. Це ще важливіше з критично важливим кодом.

Детальніше про безпеку та умови перегонів: http://www.ibm.com/developerworks/library/l-sprace.html


30

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

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

Це не так приємно, як boost :: filesystem :: існує, оскільки файл буде фактично відкритий ... але тоді це, як правило, наступне, що ви хочете зробити в будь-якому випадку.


15
Але за допомогою цього коду ви також можете перейти до речення if, якщо у вас немає дозволів на файл, хоча він існує. У більшості випадків це не має значення, але все ж варто згадати.
вчений

1
Помічено , що добре () дає також вірно , якщо даний аргумент позначає каталог, см stackoverflow.com/questions/9591036 / ...
FelixJongleur42

12

Використовуйте stat (), якщо він достатньо крос-платформний для ваших потреб. Це не стандарт C ++, але POSIX.

У MS Windows існує _stat, _stat64, _stati64, _wstat, _wstat64, _wstati64.


1
<sys / types.h> та <sys / stat.h> Див. msdn.microsoft.com/en-us/library/14h5k7ff(VS.71).aspx
Activout.se

1
Приємна відповідь +1 за те, що НЕ ВИКОРИСТОВУЄТЬСЯ BOOST , оскільки це надмір, але це не тривіально, щоб написати це з того, що тут представлено, тому я просто опублікував відповідь. Перевірте, будь ласка.
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подібну програму? Я здогадуюсь, що оригінальний плакат тут взагалі не хоче відкривати файл. Функція stat Posix, як передбачається, дає вам інформацію про дозволи файлу, тому це вирішить цю проблему.
Майкл

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;
}

3

НЕМАЄ ПОТРІБНО , що було б надмірним .


Використовуйте stat () (але не на різних платформах, хоча, як згадував pavon), ось так:

#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...

Ще одну версію (і ту) можна знайти тут .


Не голос проти, але питання задало крос-платформне рішення, і статистика існує не на всіх платформах.
павон

0

Якщо ви вже використовуєте клас потоку вхідних файлів ( ifstream), ви можете використовувати його функцію fail().

Приклад:

ifstream myFile;

myFile.open("file.txt");

// Check for errors
if (myFile.fail()) {
    cerr << "Error: File could not be found";
    exit(1);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.