write read example ejemplo c++ c file stream

read - ¿La forma más rápida de verificar si existe un archivo utilizando C++/C++ 11/C estándar?



readfile c++ (17)

Aunque hay varias formas de hacer esto, la solución más eficiente para su problema probablemente sería utilizar uno de los métodos predefinidos de fstream, como good () . Con este método puede verificar si el archivo que ha especificado existe o no.

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

Espero que encuentres esto útil.

Me gustaría encontrar la forma más rápida de verificar si existe un archivo en el estándar C ++ 11, C ++ o C. Tengo miles de archivos y, antes de hacer algo, debo comprobar si existen todos. ¿Qué puedo escribir en lugar de /* SOMETHING */ en la siguiente función?

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


Bueno, armé un programa de prueba que ejecutó cada uno de estos métodos 100.000 veces, la mitad en archivos que existían y la mitad en archivos que no.

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

Resultados del tiempo total para ejecutar las 100.000 llamadas promediadas en 5 ejecuciones,

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 función stat() proporcionó el mejor rendimiento en mi sistema (Linux, compilado con g++ ), siendo su mejor opción si por alguna razón se niega a usar las funciones POSIX.


Depende de donde residan los archivos. Por ejemplo, si se supone que todos están en el mismo directorio, puede leer todas las entradas del directorio en una tabla hash y luego verificar todos los nombres con la tabla hash. Esto podría ser más rápido en algunos sistemas que revisar cada archivo individualmente. La forma más rápida de verificar cada archivo individualmente depende de su sistema ... si está escribiendo ANSI C, la forma más rápida es la de fopen porque es la única manera (un archivo puede existir pero no puede abrirse, pero probablemente desee abrirlo si necesitas "hacer algo en ello"). C ++, POSIX, Windows ofrecen opciones adicionales.

Mientras estoy en eso, permítame señalar algunos problemas con su pregunta. Dice que desea la forma más rápida y que tiene miles de archivos, pero luego solicita el código para que una función pruebe un solo archivo (y esa función solo es válida en C ++, no en C). Esto contradice sus requisitos al hacer una suposición acerca de la solución ... un caso del problema XY . También dice "en el estándar c ++ 11 (o) c ++ (o) c" ... que son todos diferentes, y esto también es inconsistente con su requisito de velocidad ... la solución más rápida consistiría en adaptar el código a la objetivo del sistema. La incoherencia en la pregunta se destaca por el hecho de que aceptó una respuesta que brinda soluciones que dependen del sistema y no son estándar C o C ++.


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


Lo mismo que sugiere PherricOxide pero en C

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


Necesito una función rápida que pueda verificar si un archivo existe o no, y la respuesta de PherricOxide es casi lo que necesito, excepto que no compara el rendimiento de boost :: filesystem :: existe y abre funciones. De los resultados de referencia podemos ver fácilmente que:

  • El uso de la función stat es la forma más rápida de verificar si existe un archivo. Tenga en cuenta que mis resultados son consistentes con los de la respuesta de PherricOxide.

  • El rendimiento de la función boost :: filesystem :: existir es muy similar al de stat y también es portátil. Recomendaría esta solución si se puede acceder a las bibliotecas boost desde su código.

Resultados de referencia obtenidos con el kernel de Linux 4.17.0 y 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

A continuación se muestra mi código de referencia:

#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();


Nota: en C ++ 14 y tan pronto como el sistema de archivos TS se termine y se adopte, la solución será utilizar:

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

y desde C ++ 17, solo:

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


Otras 3 opciones bajo 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; }


Para los que les gusta impulsar:

boost::filesystem::exists(fileName)


Puede usar std::ifstream , std::ifstream como is_open , fail , por ejemplo, como el código siguiente (el cout "open" significa que el archivo existe o no):

citado de esta answer


Si necesita distinguir entre un archivo y un directorio, considere lo siguiente, que usa stat, que es la herramienta estándar más rápida, como lo demuestra 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; }


Sin usar otras bibliotecas, me gusta usar el siguiente fragmento de código:

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

Esto funciona multiplataforma para Windows y sistemas compatibles con POSIX.


También puede hacer bool b = std::ifstream(''filename'').good(); . Sin las instrucciones de bifurcación (como si) debe ejecutarse más rápido, ya que debe llamarse miles de veces.


Usando MFC es posible con lo siguiente

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

Donde FileName es una cadena que representa el archivo que está comprobando la existencia


Yo uso este pedazo de código, funciona bien conmigo hasta ahora. Esto no usa muchas características extravagantes de C ++:

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


all_of (begin(R), end(R), [](auto&p){ exists(p); })

donde R es su secuencia de cosas parecidas a una ruta, y exists() es del futuro std o impulso actual. Si haces tu propio rollo, hazlo simple,

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

La solución ramificada no es absolutamente terrible y no engullirá descriptores de archivos,

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 }


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