Saya ingin menemukan cara tercepat untuk memeriksa apakah ada file dalam standar C ++ 11, C ++, atau C. Saya memiliki ribuan file dan sebelum melakukan sesuatu pada mereka, saya perlu memeriksa apakah semuanya ada. Apa yang bisa saya tulis alih-alih /* SOMETHING */
dalam fungsi berikut?
inline bool exist(const std::string& name)
{
/* SOMETHING */
}
boost::filesystem
tampaknya digunakanstat()
. (Dengan asumsi dari dokumentasi.) Saya tidak berpikir Anda bisa melakukan lebih cepat untuk panggilan FS. Cara untuk mempercepat apa yang Anda lakukan adalah "hindari melihat ribuan file."git push
mungkin tidak repot-repot memastikan Anda tidak menyentuh pohon kerja setelah pemeriksaan kotor awal.Jawaban:
Yah saya mengumpulkan program pengujian yang menjalankan masing-masing metode ini 100.000 kali, setengah pada file yang ada dan setengah pada file yang tidak.
Hasil untuk total waktu untuk menjalankan 100.000 panggilan dengan rata-rata lebih dari 5 kali,
The
stat()
fungsi yang disediakan kinerja terbaik pada sistem saya (Linux, yang disusun dengang++
), dengan standarfopen
panggilan menjadi taruhan terbaik Anda jika Anda untuk beberapa alasan menolak untuk menggunakan fungsi POSIX.sumber
stat()
tampaknya memeriksa keberadaan.f.close()
karena f keluar dari ruang lingkup di akhir fungsi. Jadireturn f.good()
bisakah gantiif
blok?Catatan: di C ++ 14 dan segera setelah filesystem TS selesai dan diadopsi, solusinya adalah menggunakan:
dan sejak C ++ 17, hanya:
sumber
std::tr2::sys::exists("helloworld.txt");
std::exists
, itu akan sangat membingungkan (pikirkan: ada dalam wadah STL seperti set).#include <experimental/filesystem> bool file_exists(std::string fn) { std::experimental::filesystem::exists("helloworld.txt"); }
#include <experimental/filesystem>
Saya menggunakan kode ini, ia bekerja dengan baik sejauh ini. Ini tidak menggunakan banyak fitur mewah C ++:
sumber
ifstream
akan dipanggil saat keluaris_file_exist
dan akan menutup aliran.return std::ifstream(fileName);
Itu tergantung di mana file berada. Misalnya, jika mereka semua seharusnya berada di direktori yang sama, Anda dapat membaca semua entri direktori ke dalam tabel hash dan kemudian memeriksa semua nama terhadap tabel hash. Ini mungkin lebih cepat pada beberapa sistem daripada memeriksa setiap file satu per satu. Cara tercepat untuk memeriksa setiap file secara terpisah tergantung pada sistem Anda ... jika Anda menulis ANSI C, cara tercepat adalah
fopen
karena itu satu-satunya cara (file mungkin ada tetapi tidak dapat dibuka, tetapi Anda mungkin benar-benar ingin dapat dibuka jika Anda perlu "melakukan sesuatu di atasnya"). C ++, POSIX, Windows semua menawarkan opsi tambahan.Sementara saya melakukannya, izinkan saya menunjukkan beberapa masalah dengan pertanyaan Anda. Anda mengatakan bahwa Anda menginginkan cara tercepat, dan Anda memiliki ribuan file, tetapi kemudian Anda meminta kode untuk fungsi untuk menguji satu file (dan fungsi itu hanya valid dalam C ++, bukan C). Ini bertentangan dengan kebutuhan Anda dengan membuat asumsi tentang solusi ... kasus masalah XY . Anda juga mengatakan "dalam standar c ++ 11 (atau) c ++ (atau) c" ... yang semuanya berbeda, dan ini juga tidak konsisten dengan kebutuhan Anda akan kecepatan ... solusi tercepat akan melibatkan menyesuaikan kode dengan sistem target. Ketidakkonsistenan dalam pertanyaan disorot oleh fakta bahwa Anda menerima jawaban yang memberikan solusi yang bergantung pada sistem dan bukan standar C atau C ++.
sumber
Bagi mereka yang suka meningkatkan:
sumber
Tanpa menggunakan pustaka lain, saya suka menggunakan potongan kode berikut:
Ini berfungsi lintas platform untuk sistem yang kompatibel dengan Windows dan POSIX.
sumber
unistd.h
juga. Mungkin yang pertama#ifdef
harus spesifik windows?Sama seperti yang disarankan oleh PherricOxide tetapi dalam C
sumber
sumber
close()
tidak perlu.3 pilihan lain di bawah windows:
1
2
3
sumber
GetFileAttributes
Versi pada dasarnya adalah cara kanonik untuk melakukannya pada Windows.Anda mungkin juga melakukannya
bool b = std::ifstream('filename').good();
. Tanpa instruksi cabang (seperti jika) itu harus bekerja lebih cepat karena perlu dipanggil ribuan kali.sumber
Jika Anda perlu membedakan antara file dan direktori, pertimbangkan hal berikut yang keduanya menggunakan stat yang merupakan alat standar tercepat seperti yang ditunjukkan oleh PherricOxide:
sumber
Saya memerlukan fungsi cepat yang dapat memeriksa apakah ada file atau tidak dan jawaban PherricOxide hampir apa yang saya butuhkan kecuali tidak membandingkan kinerja boost :: filesystem :: ada dan fungsi terbuka. Dari hasil patokan kita dapat dengan mudah melihat bahwa:
Menggunakan fungsi stat adalah cara tercepat untuk memeriksa apakah ada file. Perhatikan bahwa hasil saya konsisten dengan jawaban PherricOxide.
Kinerja fungsi boost :: filesystem :: ada sangat dekat dengan fungsi stat dan juga portabel. Saya akan merekomendasikan solusi ini jika meningkatkan perpustakaan dapat diakses dari kode Anda.
Hasil benchmark diperoleh dengan kernel Linux 4.17.0 dan gcc-7.3:
Di bawah ini adalah kode benchmark saya:
sumber
Anda dapat menggunakan
std::ifstream
, seperti fungsiis_open
,,fail
misalnya seperti kode di bawah ini ("terbuka" berarti file ada atau tidak):dikutip dari jawaban ini
sumber
di mana
R
urutan hal-hal seperti jalur Anda, danexists()
dari masa depan std atau dorongan saat ini. Jika Anda menggulung sendiri, sederhanakan,Solusi bercabang tidak benar-benar mengerikan dan tidak akan melahap deskriptor file,
sumber
PathFileExists
terbatas padaMAX_PATH
(260) karakter;GetFileAttributes
tidak memiliki batasan ini.GetFileAttributes
terbatas pada MAX_PATH juga. Dokumen menjelaskan solusi jika Anda menggunakan jalur absolut, unicode, dan menambahkan string awalan khusus ke nama jalur. Saya pikir kita tidak setuju dengan respons khusus Windows.GetFileAttributesW
tidak memiliki batasan.Di C ++ 17:
sumber
Menggunakan MFC dimungkinkan dengan yang berikut ini
Di mana
FileName
string mewakili file yang Anda periksa keberadaannyasumber
hanya ada satu cara yang lebih cepat untuk memeriksa apakah file itu ada dan jika Anda memiliki izin untuk membacanya caranya menggunakan bahasa C yang ingin lebih cepat dan dapat digunakan juga dalam versi apa pun di C ++
solusi : di C ada pustaka errno.h yang memiliki variabel integer eksternal (global) yang disebut errno yang berisi angka yang dapat digunakan untuk mengenali jenis kesalahan
sumber
Meskipun ada beberapa cara untuk melakukan ini, solusi paling efisien untuk masalah Anda mungkin akan menggunakan salah satu metode yang telah ditentukan fstream seperti good () . Dengan metode ini Anda dapat memeriksa apakah file yang Anda tentukan ada atau tidak.
Saya harap Anda menemukan ini berguna.
sumber