Cách tốt nhất để kiểm tra xem tệp có tồn tại trong C ++ hay không? (nền tảng chéo)


97

Tôi đã đọc câu trả lời cho Cách tốt nhất để kiểm tra xem tệp có tồn tại trong C hay không? (đa nền tảng) , nhưng tôi tự hỏi liệu có cách nào tốt hơn để thực hiện việc này bằng cách sử dụng libs c ++ chuẩn không? Tốt nhất là không cần cố gắng mở tệp.

Cả hai stataccessđều không có khả năng Google. Tôi nên #includesử dụng những gì?


<io.h> để truy cập (thực ra có thể là _access).
Rob

Có, như từ đó đã chỉ ra.
c0m4

Câu trả lời:


170

Sử dụng boost :: filesystem :

#include <boost/filesystem.hpp>

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

68
Có vẻ là một chút của một hazzle để cài đặt một thư viện của bên thứ ba rất lớn để làm điều gì đó nên được đơn giản
c0m4

89
Boost là một thư viện mà phần lớn những gì cuối cùng sẽ là một phần của thư viện chuẩn C ++ được phát triển. Nhiều người liên quan đến boost là những người liên quan đến tiêu chuẩn C ++. Vì vậy, boost không chỉ là bất kỳ thư viện nào của bên thứ ba. Nếu bạn đang lập trình bằng C ++, bạn nên cài đặt boost!
Andreas Magnusson

Dường như tôi nhớ lại rằng b :: fs :: being trả về "true" trên các tệp không tồn tại trên mạng chia sẻ: "\\ machine \ share \ this_file_doesnt_exist" => true. Lần cuối tôi kiểm tra là tăng 1.33, hãy thận trọng ...
rlerallut

Nếu trình biên dịch của bạn có triển khai tr1, bạn thậm chí không cần cài đặt Boost. Nó sẽ nằm trong std :: tr1 :: hệ thống tập tin
Nemanja Trifunović

1
Trên thực tế ASFAIK nó không tạo ra TR1 nhưng sẽ được thêm vào ở giai đoạn sau. Tôi cũng không tìm thấy bất kỳ tham chiếu nào đến nó trong bản nháp TR1 chính thức: open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
Andreas Magnusson

41

Cẩn thận với các điều kiện chủng tộc: nếu tệp biến mất giữa lần kiểm tra "tồn tại" và thời điểm bạn mở nó, chương trình của bạn sẽ bị lỗi bất ngờ.

Tốt hơn hết là bạn nên mở tệp, kiểm tra xem có hỏng hóc không và nếu tất cả đều ổn thì hãy làm gì đó với tệp. Nó thậm chí còn quan trọng hơn với mã bảo mật quan trọng.

Thông tin chi tiết về điều kiện bảo mật và cuộc đua: http://www.ibm.com/developerworks/library/l-sprace.html


30

Tôi là một người dùng tăng cường vui vẻ và chắc chắn sẽ sử dụng giải pháp của Andreas. Nhưng nếu bạn không có quyền truy cập vào boost libs, bạn có thể sử dụng thư viện luồng:

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

Nó không hoàn toàn đẹp bằng boost :: filesystem :: tồn tại vì tệp sẽ thực sự được mở ... nhưng đó thường là điều tiếp theo bạn muốn làm.


15
Nhưng với mã này, bạn cũng sẽ chuyển sang mệnh đề if nếu bạn không có quyền đối với tệp, mặc dù nó tồn tại. Trong hầu hết các trường hợp, nó sẽ không thành vấn đề, nhưng vẫn đáng nói.
scigor

1
Nhận thấy rằng good () cũng cho kết quả đúng nếu đối số đã cho biểu thị một thư mục, hãy xem stackoverflow.com/questions/9591036/…
FelixJongleur42

12

Sử dụng stat (), nếu nó đủ đa nền tảng cho nhu cầu của bạn. Tuy nhiên, nó không phải là tiêu chuẩn C ++ mà là POSIX.

Trên MS Windows có _stat, _stat64, _stati64, _wstat, _wstat64, _wstati64.


1
<sys / styles.h> và <sys / stat.h> Xem msdn.microsoft.com/en-us/library/14h5k7ff(VS.71).aspx
activout.se

1
Câu trả lời tuyệt vời +1 cho việc KHÔNG SỬ DỤNG SÁCH , vì đó là một mức quá mức cần thiết, tuy nhiên, việc viết điều đó từ những gì được cung cấp ở đây không phải là điều tầm thường, vì vậy tôi chỉ đăng một câu trả lời. Vui lòng kiểm tra nó.
gsamaras

9

Làm thế nào về access?

#include <io.h>

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

Io.h normaly có khả dụng trên windows và linux ngay cả khi nó không phải là chuẩn không?
c0m4

1
access () là hàm POSIX khả dụng qua <unistd.h> trên Linux.
Alex B

9

Một khả năng khác bao gồm việc sử dụng good()hàm trong luồng:

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

7

Tôi sẽ xem xét lại việc cố gắng tìm xem có tệp nào tồn tại hay không. Thay vào đó, bạn nên cố gắng mở nó (trong Standard C hoặc C ++) ở cùng một chế độ mà bạn định sử dụng nó. Cách sử dụng là biết rằng tệp tồn tại nếu, chẳng hạn, nó không thể ghi được khi bạn cần sử dụng?


Điều gì sẽ xảy ra nếu bạn đang viết một lschương trình giống như vậy? Tôi đoán người đăng ban đầu ở đây không muốn mở tập tin. Chức năng thống kê của Posix được cho là cung cấp cho bạn thông tin về các quyền của tệp, vì vậy nó sẽ khắc phục sự cố đó.
Michael

6

Nếu trình biên dịch của bạn hỗ trợ C ++ 17, bạn không cần tăng cường, bạn chỉ cần sử dụng 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

KHÔNG BẮT BUỘC , đó sẽ là một sự quá mức cần thiết .


Sử dụng stat () (không phải nền tảng chéo mặc dù như được đề cập bởi pavon), như thế này:

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

Đầu ra:

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

Một phiên bản khác (và cái đó) có thể được tìm thấy ở đây .


Không phải người ủng hộ mà là câu hỏi đặt ra cho một giải pháp đa nền tảng và chỉ số không tồn tại trên tất cả các nền tảng.
pavon

0

Nếu bạn đang sử dụng lớp luồng tệp đầu vào ( ifstream), bạn có thể sử dụng hàm của nó fail().

Thí dụ:

ifstream myFile;

myFile.open("file.txt");

// Check for errors
if (myFile.fail()) {
    cerr << "Error: File could not be found";
    exit(1);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.