Je voudrais trouver le moyen le plus rapide de vérifier si un fichier existe en standard C ++ 11, C ++ ou C. J'ai des milliers de fichiers et avant de faire quelque chose, je dois vérifier s'ils existent tous. Que puis-je écrire au lieu de /* SOMETHING */
dans la fonction suivante?
inline bool exist(const std::string& name)
{
/* SOMETHING */
}
boost::filesystem
semble utiliserstat()
. (En supposant d'après la documentation.) Je ne pense pas que vous puissiez faire beaucoup plus rapidement pour les appels FS. La façon de faire ce que vous faites rapidement est «d'éviter de regarder des milliers de fichiers».git push
ne vous embêtez probablement pas à vous assurer que vous ne touchez pas à l'arbre de travail après la vérification initiale.Réponses:
Eh bien, j'ai créé un programme de test qui exécutait chacune de ces méthodes 100 000 fois, la moitié sur des fichiers qui existaient et l'autre sur des fichiers qui n'existaient pas.
Résultats pour le temps total pour exécuter les 100 000 appels en moyenne sur 5 cycles,
La
stat()
fonction a fourni les meilleures performances sur mon système (Linux, compilé avecg++
), avec unfopen
appel standard étant votre meilleur pari si vous refusez pour une raison quelconque d'utiliser les fonctions POSIX.la source
stat()
semble vérifier l'existence.f.close()
car f sort du cadre à la fin de la fonction. Alorsreturn f.good()
pourrait remplacer leif
bloc?Remarque: en C ++ 14 et dès que le système de fichiers TS sera terminé et adopté, la solution sera d'utiliser:
et depuis C ++ 17, seulement:
la source
std::tr2::sys::exists("helloworld.txt");
std::exists
, ce serait assez déroutant (pensez: existe dans un conteneur STL comme un ensemble).#include <experimental/filesystem> bool file_exists(std::string fn) { std::experimental::filesystem::exists("helloworld.txt"); }
#include <experimental/filesystem>
J'utilise ce morceau de code, cela fonctionne bien avec moi jusqu'à présent. Cela n'utilise pas de nombreuses fonctionnalités sophistiquées de C ++:
la source
ifstream
destructeur sera appelé à la sortieis_file_exist
et fermera le flux.return std::ifstream(fileName);
Cela dépend de l'emplacement des 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 vérifier tous les noms par rapport à la table de hachage. Cela peut être plus rapide sur certains systèmes que de vérifier chaque fichier individuellement. La façon la plus rapide de vérifier chaque fichier individuellement dépend de votre système ... si vous écrivez ANSI C, la façon la plus rapide est
fopen
parce que c'est la seule façon (un fichier peut exister mais ne peut pas être ouvert, mais vous voulez probablement vraiment l'ouvrir si vous besoin de "faire quelque chose"). C ++, POSIX, Windows offrent tous des options supplémentaires.Pendant que j'y suis, permettez-moi de souligner quelques problèmes avec votre question. Vous dites que vous voulez le moyen le plus rapide et que vous avez des milliers de fichiers, mais vous demandez ensuite le code d'une fonction pour tester un seul fichier (et cette fonction n'est valide qu'en C ++, pas en C). Cela contredit vos exigences en faisant une hypothèse sur la solution ... un cas du problème XY . Vous dites également "en standard c ++ 11 (ou) c ++ (ou) c" ... qui sont tous différents, et cela est également incompatible avec votre exigence de vitesse ... la solution la plus rapide consisterait à adapter le code à la système cible. L'incohérence dans la question est mise en évidence par le fait que vous avez accepté une réponse qui donne des solutions qui dépendent du système et ne sont pas du C ou du C ++ standard.
la source
Pour ceux qui aiment le boost:
la source
Sans utiliser d'autres bibliothèques, j'aime utiliser l'extrait de code suivant:
Cela fonctionne sur plusieurs plates-formes pour les systèmes Windows et compatibles POSIX.
la source
unistd.h
aussi l' inclure . Peut-être que le premier#ifdef
devrait être spécifique à Windows?Identique à celle suggérée par PherricOxide mais en C
la source
la source
close()
n'est pas nécessaire.3 autres options sous Windows:
1
2
3
la source
GetFileAttributes
version est fondamentalement la manière canonique de le faire dans Windows.Vous pouvez également le faire
bool b = std::ifstream('filename').good();
. Sans les instructions de branchement (comme si), il doit fonctionner plus rapidement car il doit être appelé des milliers de fois.la source
Si vous devez faire la distinction entre un fichier et un répertoire, tenez compte des éléments suivants, qui utilisent tous deux stat, l'outil standard le plus rapide, comme le montre PherricOxide:
la source
J'ai besoin d'une fonction rapide qui peut vérifier si un fichier existe ou non et la réponse de PherricOxide est presque ce dont j'ai besoin, sauf qu'elle ne compare pas les performances de boost :: filesystem :: exist et les fonctions ouvertes. D'après les résultats de référence, nous pouvons facilement constater que:
L'utilisation de la fonction stat est le moyen le plus rapide de vérifier si un fichier existe. Notez que mes résultats sont cohérents avec ceux de la réponse de PherricOxide.
La performance de la fonction boost :: filesystem :: exist est très proche de celle de la fonction stat et elle est également portable. Je recommanderais cette solution si les bibliothèques boost sont accessibles à partir de votre code.
Résultats de référence obtenus avec le noyau Linux 4.17.0 et gcc-7.3:
Voici mon code de référence:
la source
Vous pouvez utiliser
std::ifstream
, funcion commeis_open
,fail
par exemple comme ci - dessous le code (le Cout exist fichier « ouvert » moyens ou non):cité à partir de cette réponse
la source
où
R
est votre séquence de choses semblables à un chemin, etexists()
vient du futur std ou boost actuel. Si vous lancez le vôtre, restez simple,La solution ramifiée n'est pas absolument terrible et ne gobera pas les descripteurs de fichiers,
la source
PathFileExists
est limité àMAX_PATH
(260) caractères;GetFileAttributes
n'a pas cette limitation.GetFileAttributes
est également limité à MAX_PATH. Les documents décrivent une solution de contournement si vous utilisez des chemins absolus, unicode et ajoutez une chaîne de préfixe spéciale au nom du chemin. Je pense que nous sommes de toute façon tangents avec les réponses spécifiques à Windows.GetFileAttributesW
n'a pas de limitation.En C ++ 17:
la source
En utilisant MFC, il est possible avec les éléments suivants
Où se
FileName
trouve une chaîne représentant le fichier dont vous vérifiez l'existencela source
il n'y a qu'une seule façon plus rapide de vérifier si le fichier existe et si vous avez la permission de le lire, la façon d'utiliser le langage C est plus rapide et peut être utilisée aussi dans n'importe quelle version en C ++
solution : en C il y a une bibliothèque errno.h qui a une variable entière (globale) externe appelée errno qui contient un nombre qui peut être utilisé pour reconnaître le type d'erreur
la source
Bien qu'il existe plusieurs façons de le faire, la solution la plus efficace à votre problème serait probablement d'utiliser l'une des méthodes prédéfinies du fstream telles que good () . Avec cette méthode, vous pouvez vérifier si le fichier que vous avez spécifié existe ou non.
J'espère que vous trouvez ça utile.
la source