Apa cara terbaik untuk memeriksa apakah file ada di C ++? (lintas platform)


97

Saya telah membaca jawaban untuk Apa cara terbaik untuk memeriksa apakah file ada di C? (lintas platform) , tetapi saya bertanya-tanya apakah ada cara yang lebih baik untuk melakukan ini menggunakan c ++ libs standar? Lebih disukai tanpa mencoba membuka file sama sekali.

Keduanya statdan accesscukup tidak dapat di Google. Apa yang harus saya #includegunakan untuk menggunakan ini?


<io.h> untuk akses (yang mungkin sebenarnya adalah _access).
Rob

Ya, seperti yang ditunjukkan di sini.
c0m4

Jawaban:


170

Gunakan boost :: filesystem :

#include <boost/filesystem.hpp>

if ( !boost::filesystem::exists( "myfile.txt" ) )
{
  std::cout << "Can't find my file!" << std::endl;
}

68
Tampaknya agak menyebalkan untuk menginstal perpustakaan pihak ketiga yang besar untuk melakukan sesuatu yang seharusnya sederhana
c0m4

89
Boost adalah pustaka tempat banyak dari apa yang pada akhirnya akan menjadi bagian dari pustaka standar C ++ dikembangkan. Banyak orang yang terlibat dengan peningkatan adalah orang-orang yang terlibat dengan standar C ++. Jadi peningkatan bukan sembarang pustaka pihak ketiga. Jika Anda memprogram dalam C ++, Anda seharusnya sudah menginstal boost!
Andreas Magnusson

Sepertinya saya ingat bahwa b :: fs :: existing mengembalikan "true" pada file yang tidak ada di jaringan bersama: "\\ machine \ share \ this_file_doesnt_exist" => true. Terakhir kali saya memeriksa adalah pada peningkatan 1,33, gunakan hati-hati ...
rlerallut

Jika kompiler Anda dilengkapi dengan implementasi tr1, Anda bahkan tidak perlu menginstal Boost. Ini akan ada di std :: tr1 :: filesystem
Nemanja Trifunovic

1
Sebenarnya ASFAIK itu tidak membuat TR1 tapi akan ditambahkan nanti. Saya juga tidak menemukan referensi apa pun tentang itu di draf TR1 resmi: open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
Andreas Magnusson

41

Berhati-hatilah dengan kondisi balapan: jika file menghilang antara pemeriksaan "ada" dan saat Anda membukanya, program Anda akan gagal secara tidak terduga.

Lebih baik pergi dan buka file, periksa kegagalan dan jika semuanya baik maka lakukan sesuatu dengan file tersebut. Ini bahkan lebih penting dengan kode keamanan kritis.

Detail tentang keamanan dan kondisi ras: http://www.ibm.com/developerworks/library/l-sprace.html


30

Saya adalah pengguna yang senang meningkatkan dan pasti akan menggunakan solusi Andreas. Tetapi jika Anda tidak memiliki akses ke boost libs, Anda dapat menggunakan perpustakaan aliran:

ifstream file(argv[1]);
if (!file)
{
    // Can't open file
}

Ini tidak sebagus boost :: filesystem :: existing karena file sebenarnya akan dibuka ... tapi biasanya itu adalah hal berikutnya yang ingin Anda lakukan.


15
Tetapi dengan kode ini Anda juga akan melompat ke klausa if jika Anda tidak memiliki izin untuk file tersebut, meskipun itu ada. Dalam kebanyakan kasus, itu tidak masalah, tetapi masih layak untuk disebutkan.
scigor

1
Memperhatikan bahwa good () juga menghasilkan true jika argumen yang diberikan menunjukkan direktori, lihat stackoverflow.com/questions/9591036/…
FelixJongleur42

12

Gunakan stat (), jika cukup lintas platform untuk kebutuhan Anda. Ini bukan standar C ++, tapi POSIX.

Di MS Windows ada _stat, _stat64, _stati64, _wstat, _wstat64, _wstati64.


1
<sys / types.h> dan <sys / stat.h> Lihat msdn.microsoft.com/en-us/library/14h5k7ff(VS.71).aspx
activout.se

1
Jawaban bagus +1 untuk TIDAK MENGGUNAKAN PENINGKATAN , karena ini berlebihan, namun tidak sepele untuk menulisnya dari apa yang disediakan di sini, jadi saya baru saja memposting jawaban. Tolong periksa.
gsamaras

9

Bagaimana dengan access?

#include <io.h>

if (_access(filename, 0) == -1)
{
    // File does not exist
}

Apakah io.h normaly tersedia di windows dan linux meskipun tidak standar?
c0m4

1
access () adalah fungsi POSIX yang tersedia melalui <unistd.h> di Linux.
Alex B

9

Kemungkinan lain terdiri dari penggunaan good()fungsi di aliran:

#include <fstream>     
bool checkExistence(const char* filename)
{
     ifstream Infield(filename);
     return Infield.good();
}

7

Saya akan mempertimbangkan kembali mencoba mencari tahu apakah ada file. Sebaliknya, Anda harus mencoba membukanya (dalam Standar C atau C ++) dalam mode yang sama dengan yang Anda inginkan. Apa gunanya mengetahui bahwa file tersebut ada jika, katakanlah, tidak dapat ditulis saat Anda perlu menggunakannya?


Bagaimana jika Anda sedang menulis lsprogram yang -seperti? Saya menduga poster asli di sini tidak ingin membuka file sama sekali. Fungsi stat Posix seharusnya memberi Anda informasi tentang izin file, jadi itu akan memperbaiki masalah itu.
Michael

6

Jika kompiler Anda mendukung C ++ 17, Anda tidak perlu boost, Anda cukup menggunakan std::filesystem::exists

#include <iostream> // only for std::cout
#include <filesystem>

if (!std::filesystem::exists("myfile.txt"))
{
    std::cout << "File not found!" << std::endl;
}

3

TIDAK DIBUTUHKAN , yang akan menjadi pembunuhan besar - besaran .


Gunakan stat () (bukan cross platform meskipun seperti yang disebutkan oleh pavon), seperti ini:

#include <sys/stat.h>
#include <iostream>

// true if file exists
bool fileExists(const std::string& file) {
    struct stat buf;
    return (stat(file.c_str(), &buf) == 0);
}

int main() {
    if(!fileExists("test.txt")) {
        std::cerr << "test.txt doesn't exist, exiting...\n";
        return -1;
    }
    return 0;
}

Keluaran:

C02QT2UBFVH6-lm:~ gsamaras$ ls test.txt
ls: test.txt: No such file or directory
C02QT2UBFVH6-lm:~ gsamaras$ g++ -Wall main.cpp
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
test.txt doesn't exist, exiting...

Versi lain (dan itu) dapat ditemukan di sini .


Bukan downvoter, tetapi pertanyaan menanyakan solusi lintas platform, dan stat tidak ada di semua platform.
pavon

0

Jika Anda sudah menggunakan kelas aliran file input ( ifstream), Anda dapat menggunakan fungsinya fail().

Contoh:

ifstream myFile;

myFile.open("file.txt");

// Check for errors
if (myFile.fail()) {
    cerr << "Error: File could not be found";
    exit(1);
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.