618 votes

Le moyen le plus rapide de vérifier si un fichier existe en utilisant le standard C++/C++11,14,17/C ?

Je voudrais trouver le moyen le plus rapide de vérifier si un fichier existe en C++11, 14, 17 ou C standard. J'ai des milliers de fichiers et avant de faire quelque chose sur eux, je dois vérifier s'ils existent tous. Que puis-je écrire à la place de /* SOMETHING */ dans la fonction suivante ?

inline bool exist(const std::string& name)
{
    /* SOMETHING */
}

1 votes

Je ne sais pas comment la vérification de l'existence joue sur les vitesses du processeur et du disque, mais je parie que c'est le disque qui est lent.

2 votes

boost::filesystem semble utiliser stat() . (D'après la documentation). Je ne pense pas que vous puissiez faire beaucoup plus vite pour les appels FS. Le moyen de rendre ce que vous faites rapide est "d'éviter de regarder des milliers de fichiers".

0 votes

Je pense que la réponse à cette question a déjà été donnée : [ stackoverflow.com/questions/4316442/ [1] : stackoverflow.com/questions/4316442/

999voto

PherricOxide Points 4288

J'ai créé un programme de test qui a exécuté chacune de ces méthodes 100 000 fois, la moitié sur des fichiers qui existaient et l'autre moitié sur des fichiers qui n'existaient pas.

#include <sys/stat.h>
#include <unistd.h>
#include <string>
#include <fstream>

inline bool exists_test0 (const std::string& name) {
    ifstream f(name.c_str());
    return f.good();
}

inline bool exists_test1 (const std::string& name) {
    if (FILE *file = fopen(name.c_str(), "r")) {
        fclose(file);
        return true;
    } else {
        return false;
    }   
}

inline bool exists_test2 (const std::string& name) {
    return ( access( name.c_str(), F_OK ) != -1 );
}

inline bool exists_test3 (const std::string& name) {
  struct stat buffer;   
  return (stat (name.c_str(), &buffer) == 0); 
}

Résultats pour le temps total pour exécuter les 100 000 appels en moyenne sur 5 exécutions,

Méthode

Temps

exists_test0 (ifstream)

0.485s

exists_test1 (FILE fopen)

0.302s

exists_test2 (posix access())

0.202s

exists_test3 (posix stat())

0.134s

Le site stat() a fourni les meilleures performances sur mon système (Linux, compilé avec g++ ), avec une norme fopen call étant votre meilleure option si vous refusez, pour une raison ou une autre, d'utiliser les fonctions POSIX.

50 votes

Aucune des méthodes ci-dessus ne vérifie l'existence, mais plutôt l'accessibilité. Je ne connais pas une seule méthode standard en C ou C++ pour vérifier l'existence, cependant.

15 votes

stat() semble vérifier son existence.

128 votes

Quiconque l'utilise doit se rappeler de #include <sys/stat.h> sinon il essaie d'utiliser la mauvaise stat.

271voto

Vincent Points 7758

Remarque : en C++14 et dès que la fonction Système de fichiers TS sera terminé et adopté, la solution sera d'utiliser :

std::experimental::filesystem::exists("helloworld.txt");

et depuis C++17, seulement :

std::filesystem::exists("helloworld.txt");

1 votes

Dans MS Visual Studio 2013 cette fonction est disponible sous std::tr2::sys::exists("helloworld.txt");

3 votes

J'espère vraiment que ce ne sera pas std::exists cela serait assez déroutant (pensez : existe dans un conteneur STL comme un ensemble).

4 votes

Également dans Visual Studio 2015 : #include <experimental/filesystem> bool file_exists(std::string fn) { std::experimental::filesystem::exists("helloworld.txt"); }

136voto

harryngh Points 147

J'utilise ce morceau de code, qui fonctionne bien pour moi jusqu'à présent. Il n'utilise pas beaucoup de fonctionnalités sophistiquées du C++ :

bool is_file_exist(const char *fileName)
{
    std::ifstream infile(fileName);
    return infile.good();
}

10 votes

Cependant, il peut échouer si le fichier a été verrouillé par un autre programme ou s'il n'y a pas d'accès au fichier.

4 votes

Devez-vous fermer le flux ?

37 votes

@Mo0gles : Le site ifstream Le destructeur sera appelé à la sortie is_file_exist et il fermera le flux.

30voto

Jim Balter Points 9250

Cela dépend de l'endroit où se trouvent les fichiers. Par exemple, s'ils sont tous censés se trouver dans le même répertoire, vous pouvez lire toutes les entrées du répertoire dans une table de hachage, puis comparer tous les noms à cette table. Ceci pourrait est plus rapide sur certains systèmes que de vérifier chaque fichier individuellement. La méthode la plus rapide pour vérifier chaque fichier individuellement dépend de votre système ... si vous écrivez en ANSI C, la méthode la plus rapide est la suivante fopen parce que c'est le seul moyen (un fichier peut exister mais ne pas être ouvrable, mais vous voulez probablement vraiment qu'il soit ouvrable si vous devez "faire quelque chose dessus"). C++, POSIX, Windows offrent tous des options supplémentaires.

Pendant que j'y suis, permettez-moi de souligner certains problèmes liés à votre question. Vous dites que vous voulez le moyen le plus rapide, et que vous avez des milliers de fichiers, mais ensuite vous demandez le code d'une fonction pour tester un seul fichier (et cette fonction n'est valable qu'en C++, pas en C). Cela contredit vos exigences en faisant une hypothèse sur la solution ... un cas de le problème XY . Vous dites également "en c++11(ou)c++(ou)c standard" ... qui sont tous différents, et cela est également incompatible avec votre exigence de rapidité ... la solution la plus rapide impliquerait d'adapter le code au système cible. L'incohérence de la question est soulignée par le fait que vous avez accepté une réponse qui donne des solutions qui dépendent du système et qui ne sont pas du C ou C++ standard.

25voto

Ramon La Pietra Points 49

Identique à la suggestion de PherricOxide mais en C

#include <sys/stat.h>
int exist(const char *name)
{
  struct stat   buffer;
  return (stat (name, &buffer) == 0);
}

1 votes

.c_str() est une fonction C++. Je ne connais pas le C++ donc j'ai posté un équivalent en C.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X