Chciałbym znaleźć najszybszy sposób sprawdzenia, czy plik istnieje w standardowym C ++ 11, C ++ lub C. Mam tysiące plików i zanim coś z nimi zrobię, muszę sprawdzić, czy wszystkie istnieją. Co mogę napisać zamiast /* SOMETHING */
w poniższej funkcji?
inline bool exist(const std::string& name)
{
/* SOMETHING */
}
boost::filesystem
wydaje się używaćstat()
. (Zakładając, że z dokumentacji.) Nie sądzę, że możesz zrobić znacznie szybciej dla wywołań FS. Szybkim sposobem na zrobienie tego jest „unikanie patrzenia na tysiące plików”.git push
Prawdopodobnie nie zadaje sobie trudu, aby upewnić się, że nie dotykasz działającego drzewa po początkowym brudnym sprawdzeniu.Odpowiedzi:
Cóż, rzuciłem program testowy, który uruchomił każdą z tych metod 100 000 razy, w połowie na plikach, które istniały, a na połowie na plikach, które nie istniały.
Wyniki dla całkowitego czasu na wykonanie 100 000 połączeń uśrednionych dla 5 przebiegów,
Ta
stat()
funkcja zapewniała najlepszą wydajność w moim systemie (Linux, z kompilacjąg++
), przy czym standardowefopen
wywołanie jest najlepszym wyborem, jeśli z jakiegoś powodu odmawiasz korzystania z funkcji POSIX.źródło
stat()
wydaje się sprawdzać istnienie.f.close()
ponieważ f wychodzi poza zakres na końcu funkcji. Więcreturn f.good()
może zastąpićif
blok?Uwaga: w C ++ 14 i jak tylko system plików TS zostanie ukończony i przyjęty, rozwiązaniem będzie użycie:
a od C ++ 17 tylko:
źródło
std::tr2::sys::exists("helloworld.txt");
std::exists
, byłoby to dość mylące (pomyśl: istnieje w kontenerze STL jak zestaw).#include <experimental/filesystem> bool file_exists(std::string fn) { std::experimental::filesystem::exists("helloworld.txt"); }
#include <experimental/filesystem>
Używam tego fragmentu kodu, do tej pory działa ze mną dobrze. To nie używa wielu wymyślnych funkcji C ++:
źródło
ifstream
zostanie wywołany przy wychodzeniuis_file_exist
i zamknie strumień.return std::ifstream(fileName);
To zależy od tego, gdzie znajdują się pliki. Na przykład, jeśli wszystkie mają znajdować się w tym samym katalogu, możesz odczytać wszystkie wpisy katalogu w tablicy skrótów, a następnie sprawdzić wszystkie nazwy w tabeli skrótów. W niektórych systemach może to być szybsze niż sprawdzanie każdego pliku osobno. Najszybszy sposób sprawdzenia każdego pliku osobno zależy od systemu ... jeśli piszesz ANSI C, najszybszym sposobem jest
fopen
to, że jest to jedyny sposób (plik może istnieć, ale nie da się go otworzyć, ale prawdopodobnie naprawdę chcesz go otworzyć, jeśli trzeba „coś z tym zrobić”). C ++, POSIX, Windows oferują dodatkowe opcje.Skoro już o tym mówię, pozwól mi wskazać pewne problemy z twoim pytaniem. Mówisz, że chcesz najszybszy sposób i że masz tysiące plików, ale potem pytasz o kod funkcji, by przetestować pojedynczy plik (i ta funkcja jest poprawna tylko w C ++, a nie w C). Jest to sprzeczne z Twoimi wymaganiami, zakładając, że rozwiązanie ... jest przypadkiem problemu XY . Mówisz także „w standardowym c ++ 11 (lub) c ++ (lub) c” ... które są różne, a to również jest niezgodne z twoim wymaganiem szybkości ... najszybsze rozwiązanie wymagałoby dostosowania kodu do Docelowy system. Niespójność w tym pytaniu podkreśla fakt, że zaakceptowałeś odpowiedź, która daje rozwiązania zależne od systemu i nie będące standardowym C lub C ++.
źródło
Dla tych, którzy lubią boost:
źródło
Bez używania innych bibliotek lubię używać następującego fragmentu kodu:
Działa to na wielu platformach dla systemów zgodnych z Windows i POSIX.
źródło
unistd.h
. Może pierwszy#ifdef
powinien być specyficzny dla systemu Windows?Taki sam jak sugerowany przez PherricOxide, ale w C
źródło
źródło
close()
nie jest konieczne.Kolejne 3 opcje pod oknami:
1
2)
3)
źródło
GetFileAttributes
Wersja jest w zasadzie kanoniczny sposób to zrobić w systemie Windows.Ty też możesz to zrobić
bool b = std::ifstream('filename').good();
. Bez instrukcji rozgałęzienia (np. Jeśli) musi działać szybciej, ponieważ trzeba go wywoływać tysiące razy.źródło
Jeśli potrzebujesz rozróżnić plik od katalogu, zastanów się, które z nich wykorzystują stat, które jest najszybszym standardowym narzędziem, jak wykazał PherricOxide:
źródło
Potrzebuję szybkiej funkcji, która może sprawdzić, czy plik istnieje, a odpowiedź PherricOxide jest prawie tym, czego potrzebuję, z wyjątkiem tego, że nie porównuje wydajności boost :: fileystem :: istnieje i funkcji otwartych. Z wyników testu porównawczego możemy łatwo zauważyć, że:
Korzystanie z funkcji stat jest najszybszym sposobem sprawdzenia, czy plik istnieje. Zauważ, że moje wyniki są zgodne z odpowiedzią PherricOxide.
Wydajność funkcji boost :: fileystem :: istnieje jest bardzo zbliżona do funkcji stat i jest przenośna. Poleciłbym to rozwiązanie, jeśli biblioteki rozszerzeń są dostępne z twojego kodu.
Wyniki testu porównawczego uzyskane z jądrem Linux 4.17.0 i gcc-7.3:
Poniżej znajduje się mój kod testu porównawczego:
źródło
Możesz użyć
std::ifstream
, podobnie jakis_open
,fail
np. Jak poniżej kodu („otwarte” oznacza, że plik istnieje lub nie istnieje):cytowany z tej odpowiedzi
źródło
gdzie
R
jest twoja sekwencja rzeczy podobnych do ścieżki iexists()
pochodzi z przyszłego standardowego lub obecnego wzmocnienia. Jeśli wyrzucisz własny, zachowaj prostotę,Rozgałęzione rozwiązanie nie jest absolutnie straszne i nie pożera deskryptorów plików,
źródło
PathFileExists
jest ograniczony doMAX_PATH
(260) znaków;GetFileAttributes
nie ma tego ograniczenia.GetFileAttributes
jest również ograniczony do MAX_PATH. Dokumenty opisują obejście, jeśli używasz ścieżek bezwzględnych, kodu Unicode i dołączasz specjalny ciąg prefiksu do nazwy ścieżki. Wydaje mi się, że i tak mamy styczność z odpowiedziami specyficznymi dla systemu Windows.GetFileAttributesW
nie ma ograniczeń.W C ++ 17:
źródło
Korzystanie z MFC jest możliwe w następujący sposób
Gdzie
FileName
jest ciąg reprezentujący plik, który sprawdzasz pod kątem istnieniaźródło
istnieje tylko jeden szybszy sposób, aby sprawdzić, czy plik istnieje, a jeśli masz uprawnienia do jego odczytu, sposób korzystania z języka C jest szybszy i można go również używać w dowolnej wersji w C ++
rozwiązanie : w C znajduje się biblioteka errno.h, która ma zewnętrzną (globalną) zmienną całkowitą o nazwie errno, która zawiera liczbę, której można użyć do rozpoznania rodzaju błędu
źródło
Chociaż istnieje kilka sposobów, aby to zrobić, najbardziej wydajnym rozwiązaniem Twojego problemu byłoby prawdopodobnie użycie jednej ze wstępnie zdefiniowanych metod fstream, takich jak good () . Za pomocą tej metody możesz sprawdzić, czy określony plik istnieje, czy nie.
Mam nadzieję, że uznasz to za przydatne.
źródło