La manière la plus rapide de vérifier si un fichier existe en utilisant standard C++/C++11/c?

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 sur eux, je dois vérifier si tous existent. Que puis-je écrire à la place de /* SOMETHING */ dans la fonction suivante?

inline bool exist(const std::string& name)
{
    /* SOMETHING */
}
326
demandé sur MD XF 2012-10-08 05:10:11

17 réponses

Eh bien, j'ai créé un programme d'essai 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); 
}

les Résultats pour le total des temps de courir les 100 000 appels en moyenne plus de 5 pistes,

Method exists_test0 (ifstream): **0.485s**
Method exists_test1 (FILE fopen): **0.302s**
Method exists_test2 (posix access()): **0.202s**
Method exists_test3 (posix stat()): **0.134s**

la fonction stat() a fourni les meilleures performances sur mon système (Linux, compilé avec g++ ), avec un appel standard fopen étant votre meilleur pari si vous pour une raison quelconque refusez D'utiliser les fonctions POSIX.

582
répondu PherricOxide 2018-10-05 11:31:18

j'utilise ce morceau de code, il fonctionne bien avec moi jusqu'à présent. Cela n'utilise pas beaucoup de fonctionnalités sophistiquées de C++:

bool is_file_exist(const char *fileName)
{
    std::ifstream infile(fileName);
    return infile.good();
}
83
répondu harryngh 2013-11-07 16:45:31

Remarque: En C++14 et dès que le 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");
79
répondu Vincent 2018-08-16 23:50:31

cela dépend de l'endroit où résident les fichiers. Par exemple, si ils sont tous censés être 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 sur la table de hachage. Ce pourrait être plus rapide sur certains systèmes que la vérification de chaque fichier individuellement. La manière la plus rapide de vérifier chaque fichier individuellement dépend de votre système ... si vous écrivez ANSI C, la manière la plus rapide est fopen parce que c'est la seule façon (un fichier peut-être existe mais pas ouvert, mais vous voulez probablement vraiment ouvert si vous avez besoin de"faire quelque chose sur elle"). C++, POSIX, Windows offrent toutes des options supplémentaires.

Pendant que j'y suis, permettez-moi de souligner quelques problèmes avec votre question. Vous dites que vous voulez la manière la plus rapide, et que vous avez des milliers de fichiers, mais alors vous demandez le code pour une fonction pour tester un seul fichier (et cette fonction n'est valide qu'en C++, pas en C). Ceci contredit vos exigences en faisant hypothèse sur la solution ... un cas de XY problème . Vous dites aussi "en standard C++11(ou)C++(ou)c" ... qui sont tous différents, et c'est également incompatible avec vos besoins de vitesse ... la solution la plus rapide consisterait à adapter le code au système cible. L'incohérence de 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 qui ne sont pas standard C ou C++.

25
répondu Jim Balter 2017-03-20 10:29:30

pour ceux qui aiment boost:

 boost::filesystem::exists(fileName)
21
répondu anhoppe 2015-09-21 08:30:10

Sans utiliser d'autres bibliothèques, j'aime utiliser l'extrait de code suivant:

#ifdef _WIN32
   #include <io.h> 
   #define access    _access_s
#else
   #include <unistd.h>
#endif

bool FileExists( const std::string &Filename )
{
    return access( Filename.c_str(), 0 ) == 0;
}

cela fonctionne multiplateformes pour Windows et les systèmes conformes à POSIX.

17
répondu Viktor Liehr 2016-10-05 04:07:48

identique à celle suggérée par le PherricOxide mais en C

#include <sys/stat.h>
int exist(const char *name)
{
  struct stat   buffer;
  return (stat (name, &buffer) == 0);
}
14
répondu Ramon La Pietra 2018-01-28 03:32:33
inline bool exist(const std::string& name)
{
    ifstream file(name);
    if(!file)            // If the file was not found, then file is 0, i.e. !file=1 or true.
        return false;    // The file was not found.
    else                 // If the file was found, then file is non-0.
        return true;     // The file was found.
}
9
répondu LOLOLOL 2014-09-08 15:54:45

3 autres options sous windows:

1

inline bool exist(const std::string& name)
{
    OFSTRUCT of_struct;
    return OpenFile(name.c_str(), &of_struct, OF_EXIST) != INVALID_HANDLE_VALUE && of_struct.nErrCode == 0;
}

2

inline bool exist(const std::string& name)
{
    HANDLE hFile = CreateFile(name.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile != NULL && hFile != INVALID_HANDLE)
    {
         CloseFile(hFile);
         return true;
    }
    return false;
}

3

inline bool exist(const std::string& name)
{
    return GetFileAttributes(name.c_str()) != INVALID_FILE_ATTRIBUTES;
}
6
répondu ravin.wang 2014-08-22 15:18:18

vous pouvez aussi faire bool b = std::ifstream('filename').good(); . Sans les instructions de branche (comme si) il doit effectuer plus rapidement car il doit être appelé des milliers de fois.

4
répondu parv 2014-08-25 05:48:35

si vous avez besoin de distinguer entre un fichier et un répertoire, considérer ce qui suit qui utilisent tous les deux stat qui l'outil standard le plus rapide comme démontré par le PherricOxide:

#include <sys/stat.h>
int FileExists(char *path)
{
    struct stat fileStat; 
    if ( stat(path, &fileStat) )
    {
        return 0;
    }
    if ( !S_ISREG(fileStat.st_mode) )
    {
        return 0;
    }
    return 1;
}

int DirExists(char *path)
{
    struct stat fileStat;
    if ( stat(path, &fileStat) )
    {
        return 0;
    }
    if ( !S_ISDIR(fileStat.st_mode) )
    {
        return 0;
    }
    return 1;
}
4
répondu user3902302 2015-05-21 13:30:22
all_of (begin(R), end(R), [](auto&p){ exists(p); })

R est votre séquence de choses comme le chemin, et exists() est du futur std ou boost actuel. Si vous roulez votre propre, gardez-le simple,

bool exists (string const& p) { return ifstream{p}; }

La ramifiés solution n'est pas absolument terrible et ne pas gober les descripteurs de fichiers,

bool exists (const char* p) {
    #if defined(_WIN32) || defined(_WIN64)
    return p && 0 != PathFileExists (p);
    #else
    struct stat sb;
    return p && 0 == stat (p, &sb);
    #endif
}
3
répondu John 2015-01-25 00:57:03

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'il ne compare pas les performances de boost::filesystem::exists et ouvrir des fonctions. D'après les résultats de l'analyse comparative, nous pouvons facilement voir 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 compatibles avec ceux de la réponse de PherricOxide.

  • la performance de boost::filesystem::exists fonction est très proche de celle de stat fonction et il est également portable. Je recommande cette solution si boost libraries est accessible à partir de votre code.

résultats de référence obtenus avec le noyau Linux 4.17.0 et gcc-7.3:

2018-05-05 00:35:35
Running ./filesystem
Run on (8 X 2661 MHz CPU s)
CPU Caches:
  L1 Data 32K (x4)
  L1 Instruction 32K (x4)
  L2 Unified 256K (x4)
  L3 Unified 8192K (x1)
--------------------------------------------------
Benchmark           Time           CPU Iterations
--------------------------------------------------
use_stat          815 ns        813 ns     861291
use_open         2007 ns       1919 ns     346273
use_access       1186 ns       1006 ns     683024
use_boost         831 ns        830 ns     831233

ci-dessous est mon code de référence:

#include <string.h>                                                                                                                                                                                                                                           
#include <stdlib.h>                                                                                                                                                                                                                                           
#include <sys/types.h>                                                                                                                                                                                                                                        
#include <sys/stat.h>                                                                                                                                                                                                                                         
#include <unistd.h>                                                                                                                                                                                                                                           
#include <dirent.h>                                                                                                                                                                                                                                           
#include <fcntl.h>                                                                                                                                                                                                                                            
#include <unistd.h>                                                                                                                                                                                                                                           

#include "boost/filesystem.hpp"                                                                                                                                                                                                                               

#include <benchmark/benchmark.h>                                                                                                                                                                                                                              

const std::string fname("filesystem.cpp");                                                                                                                                                                                                                    
struct stat buf;                                                                                                                                                                                                                                              

// Use stat function                                                                                                                                                                                                                                          
void use_stat(benchmark::State &state) {                                                                                                                                                                                                                      
    for (auto _ : state) {                                                                                                                                                                                                                                    
        benchmark::DoNotOptimize(stat(fname.data(), &buf));                                                                                                                                                                                                   
    }                                                                                                                                                                                                                                                         
}                                                                                                                                                                                                                                                             
BENCHMARK(use_stat);                                                                                                                                                                                                                                          

// Use open function                                                                                                                                                                                                                                          
void use_open(benchmark::State &state) {                                                                                                                                                                                                                      
    for (auto _ : state) {                                                                                                                                                                                                                                    
        int fd = open(fname.data(), O_RDONLY);                                                                                                                                                                                                                
        if (fd > -1) close(fd);                                                                                                                                                                                                                               
    }                                                                                                                                                                                                                                                         
}                                                                                                                                                                                                                                                             
BENCHMARK(use_open);                                  
// Use access function                                                                                                                                                                                                                                        
void use_access(benchmark::State &state) {                                                                                                                                                                                                                    
    for (auto _ : state) {                                                                                                                                                                                                                                    
        benchmark::DoNotOptimize(access(fname.data(), R_OK));                                                                                                                                                                                                 
    }                                                                                                                                                                                                                                                         
}                                                                                                                                                                                                                                                             
BENCHMARK(use_access);                                                                                                                                                                                                                                        

// Use boost                                                                                                                                                                                                                                                  
void use_boost(benchmark::State &state) {                                                                                                                                                                                                                     
    for (auto _ : state) {                                                                                                                                                                                                                                    
        boost::filesystem::path p(fname);                                                                                                                                                                                                                     
        benchmark::DoNotOptimize(boost::filesystem::exists(p));                                                                                                                                                                                               
    }                                                                                                                                                                                                                                                         
}                                                                                                                                                                                                                                                             
BENCHMARK(use_boost);                                                                                                                                                                                                                                         

BENCHMARK_MAIN();   
1
répondu hungptit 2018-05-05 04:51:34

vous pouvez utiliser std::ifstream , fonction comme is_open , fail , par exemple comme code ci-dessous (le trait "ouvrir" signifie que le fichier existe ou non):

enter image description here

enter image description here

Cité de ce réponse

1
répondu Jayhello 2018-07-12 08:59:55

en utilisant MFC il est possible avec le suivant

CFileStatus FileStatus;
BOOL bFileExists = CFile::GetStatus(FileName,FileStatus);

FileName est une chaîne représentant le fichier que vous vérifiez pour l'existence

0
répondu Andy Bantly 2018-01-28 03:32:38

En C++17:

#include <experimental/filesystem>

bool is_file_exist(std::string& str) {   
    namespace fs = std::experimental::filesystem;
    fs::path p(str);
    return fs::exists(p);
}
0
répondu Abhijeet Kandalkar 2018-08-28 16:25:59

Bien qu'il existe plusieurs façons pour ce faire, la solution la plus efficace à votre problème serait probablement d'utiliser l'un des fstream prédéfinis méthode comme bonne() . Avec cette méthode, vous pouvez vérifier si le fichier que vous avez spécifié existe ou pas.

fstream file("file_name.txt");

if (file.good()) 
{
    std::cout << "file is good." << endl;
}
else 
{
    std::cout << "file isnt good" << endl;
}

j'espère que vous trouverez cela utile.

-2
répondu miksiii 2014-09-17 21:19:28