Quelle est la meilleure façon de vérifier si un fichier existe en C ++? (plateforme croisée)

97

J'ai lu les réponses pour Quelle est la meilleure façon de vérifier si un fichier existe en C? (multiplate-forme) , mais je me demande s'il existe une meilleure façon de le faire en utilisant des bibliothèques C ++ standard? De préférence sans essayer d'ouvrir le fichier du tout.

Les deux statet accesssont à peu près indomptables. Que dois-je #includeutiliser pour les utiliser?

c0m4
la source
<io.h> pour l'accès (qui pourrait en fait être _access).
Rob
Oui, comme indiqué à partir de là.
c0m4

Réponses:

170

Utilisez boost :: filesystem :

#include <boost/filesystem.hpp>

if ( !boost::filesystem::exists( "myfile.txt" ) )
{
  std::cout << "Can't find my file!" << std::endl;
}
Andreas Magnusson
la source
68
Cela semble être un peu compliqué d'installer une énorme bibliothèque tierce pour faire quelque chose qui devrait être simple
c0m4
89
Boost est une bibliothèque dans laquelle une grande partie de ce qui sera éventuellement une partie de la bibliothèque standard C ++ est développée. De nombreuses personnes impliquées dans Boost sont des personnes impliquées dans la norme C ++. Donc, Boost n'est pas n'importe quelle bibliothèque tierce. Si vous programmez en C ++, vous devriez avoir installé boost!
Andreas Magnusson
Il me semble rappeler que b :: fs :: existe renvoie "true" sur des fichiers inexistants sur des partages réseau: "\\ machine \ share \ this_file_doesnt_exist" => true. La dernière fois que j'ai vérifié, c'était sur le boost 1.33,
soyez
Si votre compilateur est livré avec une implémentation tr1, vous n'avez même pas besoin d'installer Boost. Il sera dans le système de fichiers std :: tr1 ::
Nemanja Trifunovic
1
En fait, ASFAIK n'a pas fait TR1 mais sera ajouté à un stade ultérieur. Je n'ai pas non plus trouvé de références à ce sujet dans le projet officiel de TR1: open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
Andreas Magnusson
41

Attention aux conditions de concurrence: si le fichier disparaît entre le contrôle «existe» et l'heure à laquelle vous l'ouvrez, votre programme échouera de manière inattendue.

Il vaut mieux aller ouvrir le fichier, vérifier l'échec et si tout va bien, faire quelque chose avec le fichier. C'est encore plus important avec le code critique pour la sécurité.

Détails sur la sécurité et les conditions de concurrence : http://www.ibm.com/developerworks/library/l-sprace.html

rlerallut
la source
30

Je suis un utilisateur de boost heureux et j'utiliserais certainement la solution d'Andreas. Mais si vous n'avez pas accès aux bibliothèques boost, vous pouvez utiliser la bibliothèque de flux:

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

Ce n'est pas aussi bien que boost :: filesystem :: existe puisque le fichier sera en fait ouvert ... mais c'est généralement la prochaine chose que vous voulez faire de toute façon.

MattyT
la source
15
Mais avec ce code, vous sauteriez également dans la clause if si vous ne disposez pas des autorisations pour le fichier, bien qu'il existe. Dans la plupart des cas, cela n'a pas d'importance, mais cela vaut la peine d'être mentionné.
scigor le
1
Remarqué que good () donne également vrai si l'argument donné dénote un répertoire, voir stackoverflow.com/questions/9591036
...
12

Utilisez stat (), si elle est suffisamment multiplateforme pour vos besoins. Ce n'est pas le standard C ++, mais POSIX.

Sur MS Windows, il y a _stat, _stat64, _stati64, _wstat, _wstat64, _wstati64.

activout.se
la source
1
<sys / types.h> et <sys / stat.h> Voir msdn.microsoft.com/en-us/library/14h5k7ff(VS.71).aspx
activout.se
1
Bonne réponse +1 pour NE PAS UTILISER BOOST , car c'est exagéré, mais ce n'était pas trivial d'écrire cela à partir de ce qui est fourni ici, alors je viens de publier une réponse. Vérifiez-le s'il vous plaît.
gsamaras
9

Et pourquoi pas access?

#include <io.h>

if (_access(filename, 0) == -1)
{
    // File does not exist
}
Rob
la source
Io.h est-il normalement disponible sur Windows et Linux, même si ce n'est pas standard?
c0m4
1
access () est la fonction POSIX disponible via <unistd.h> sous Linux.
Alex B
9

Une autre possibilité consiste à utiliser la good()fonction dans le flux:

#include <fstream>     
bool checkExistence(const char* filename)
{
     ifstream Infield(filename);
     return Infield.good();
}
Samer
la source
7

Je reconsidérerais essayer de savoir si un fichier existe. Au lieu de cela, vous devriez essayer de l'ouvrir (en Standard C ou C ++) dans le même mode que vous avez l'intention de l'utiliser. À quoi sert de savoir que le fichier existe si, par exemple, il n'est pas accessible en écriture lorsque vous devez l'utiliser?

pétillant
la source
Et si vous écrivez un lsprogramme similaire? Je suppose que l'affiche originale ici ne veut pas du tout ouvrir le fichier. La fonction stat de Posix est censée vous donner des informations sur les permissions du fichier, donc elle résoudrait ce problème.
Michael
6

Si votre compilateur prend en charge C ++ 17, vous n'avez pas besoin de boost, vous pouvez simplement utiliser 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
la source
3

NON REQUIS , ce qui serait exagéré .


Utilisez stat () (pas multiplateforme bien que comme mentionné par pavon), comme ceci:

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

Production:

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

Une autre version (et celle) peut être trouvée ici .

gsamaras
la source
Pas le downvoter, mais la question posée pour une solution multiplateforme, et la statistique n'existe pas sur toutes les plateformes.
pavon
0

Si vous utilisez déjà la classe de flux de fichier d'entrée ( ifstream), vous pouvez utiliser sa fonction fail().

Exemple:

ifstream myFile;

myFile.open("file.txt");

// Check for errors
if (myFile.fail()) {
    cerr << "Error: File could not be found";
    exit(1);
}
Reza Saadati
la source