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.
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 utiliserstat()
. (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/
26 votes
TOCTOU question : comment savez-vous que le fichier n'est pas délié entre votre vérification de exists() et votre vérification de "faire quelque chose dessus" ?
10 votes
@pilcrow Bon point, mais il y a une gamme assez large d'applications qui n'ont pas besoin de tant de correction. Par exemple
git push
ne prend probablement pas la peine de s'assurer que vous ne touchez pas l'arbre de travail après la vérification initiale de la saleté.0 votes
@Duck
unistd.h
est POSIX, et non la libc définie de manière pédante. Bien sûr, je ne peux pas imaginer une implémentation C/C++ qui ne l'aurait pas, oustat()
sauf pour une sorte d'environnement embarqué bizarre qui ne correspond pas vraiment à l'exigence des "milliers de fichiers". Ce qui rend la restriction "pas d'API du système d'exploitation" un peu stupide, étant donné que la manipulation du système de fichiers est en effet le domaine du système d'exploitation.13 votes
Je ne peux pas penser à une implémentation C/C++ qui ne l'aurait pas" -- Windows ne fournit pas un environnement POSIX.
0 votes
Regardez ce fil : stackoverflow.com/questions/230062/
0 votes
@JimBalter : Services Windows pour Unix (Interix) ?
1 votes
@el pescado C'est un "sous-système", pas Windows lui-même.
3 votes
Duplicata possible de std::ofstream, vérifie si le fichier existe avant d'écrire
2 votes
Pourquoi ? "Faire quelque chose sur eux", comme quoi ? Si cela implique d'ouvrir le fichier, essayez simplement de l'ouvrir et gérez l'erreur s'il n'existe pas. Ajouter une autre vérification au préalable n'est qu'une perte de temps et d'énergie, et ajoute un problème de fenêtre temporelle.
1 votes
J'imagine un gros accent de Boston disant "sauce" quand je lis "une perte de temps et de soace".
0 votes
"ORLY ?" -- oui. "Ça me semble proche..." -- désolé de l'entendre.