วิธีใดที่ดีที่สุดในการตรวจสอบว่ามีไฟล์อยู่ใน C ++ หรือไม่ (ข้ามแพลตฟอร์ม)


97

ฉันได้อ่านคำตอบแล้วว่าอะไรคือวิธีที่ดีที่สุดในการตรวจสอบว่ามีไฟล์อยู่ใน C หรือไม่ (ข้ามแพลตฟอร์ม)แต่ฉันสงสัยว่ามีวิธีที่ดีกว่านี้โดยใช้ c ++ libs มาตรฐานหรือไม่ โดยเฉพาะอย่างยิ่งโดยไม่ต้องพยายามเปิดไฟล์เลย

ทั้งสองอย่างstatและไม่accessสามารถเข้าถึงได้ จะ#includeใช้อะไรดี?


<io.h> สำหรับการเข้าถึง (ซึ่งจริงๆแล้วอาจเป็น _access)
Rob

ใช่ตามที่ได้ชี้ให้เห็น
c0m4

คำตอบ:


170

ใช้boost :: filesystem :

#include <boost/filesystem.hpp>

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

68
ดูเหมือนจะเป็นเรื่องยุ่งยากเล็กน้อยที่จะติดตั้งไลบรารีของบุคคลที่สามขนาดใหญ่เพื่อทำสิ่งที่ควรจะง่าย
c0m4

89
Boost เป็นไลบรารีที่ส่วนใหญ่จะเป็นส่วนหนึ่งของไลบรารีมาตรฐาน C ++ ได้รับการพัฒนา หลายคนที่เกี่ยวข้องกับการเพิ่มประสิทธิภาพเป็นผู้ที่เกี่ยวข้องกับมาตรฐาน C ++ ดังนั้นการเพิ่มไม่ได้เป็นเพียงใดห้องสมุดของบุคคลที่สาม หากคุณกำลังเขียนโปรแกรมใน C ++ คุณควรติดตั้งเพิ่ม!
Andreas Magnusson

ฉันดูเหมือนจะจำได้ว่า b :: fs :: มีอยู่ส่งคืน "true" ในไฟล์ที่ไม่มีอยู่จริงบนเครือข่ายที่ใช้ร่วมกัน: "\\ machine \ share \ this_file_doesnt_exist" => true ครั้งล่าสุดที่ฉันตรวจสอบคือเพิ่ม 1.33 โปรดใช้ความระมัดระวัง ...
rlerallut

หากคอมไพเลอร์ของคุณมาพร้อมกับการใช้งาน tr1 คุณไม่จำเป็นต้องติดตั้ง Boost มันจะอยู่ใน std :: tr1 :: filesystem
Nemanja Trifunovic

1
ASFAIK จริงๆแล้วมันไม่ได้สร้าง TR1 แต่จะถูกเพิ่มในภายหลัง ฉันยังไม่พบการอ้างอิงใด ๆ ในร่าง TR1 อย่างเป็นทางการ: open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
Andreas Magnusson

41

ระวังเงื่อนไขการแย่งชิง: หากไฟล์หายไประหว่างการตรวจสอบ "มีอยู่" และเวลาที่คุณเปิดโปรแกรมของคุณจะล้มเหลวโดยไม่คาดคิด

จะดีกว่าที่จะไปเปิดไฟล์ตรวจสอบความล้มเหลวและหากทุกอย่างเรียบร้อยดีให้ทำอะไรกับไฟล์ สิ่งสำคัญยิ่งกว่าด้วยรหัสที่สำคัญด้านความปลอดภัย

รายละเอียดเกี่ยวกับความปลอดภัยและเงื่อนไขการแข่งขัน: http://www.ibm.com/developerworks/library/l-sprace.html


30

ฉันเป็นผู้ใช้ที่เพิ่มความสุขและจะใช้โซลูชันของ Andreas อย่างแน่นอน แต่ถ้าคุณไม่มีสิทธิ์เข้าถึง boost libs คุณสามารถใช้ไลบรารีสตรีมได้:

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

มันไม่ค่อยดีเท่า boost :: filesystem :: ที่มีอยู่เนื่องจากไฟล์จะถูกเปิดจริงๆ ... แต่โดยปกติแล้วนั่นคือสิ่งต่อไปที่คุณต้องการทำ


15
แต่ด้วยรหัสนี้คุณจะข้ามไปที่ส่วนคำสั่ง if หากคุณไม่มีสิทธิ์สำหรับไฟล์แม้ว่าจะมีอยู่ก็ตาม ในกรณีส่วนใหญ่มันจะไม่สำคัญ แต่ก็ยังคุ้มค่าที่จะกล่าวถึง
scigor

1
สังเกตเห็นว่า good () ยังให้ผลเป็นจริงหากอาร์กิวเมนต์ที่ระบุหมายถึงไดเร็กทอรีโปรดดูstackoverflow.com/questions/9591036/…
FelixJongleur42

12

ใช้ stat () หากข้ามแพลตฟอร์มเพียงพอสำหรับความต้องการของคุณ ไม่ใช่มาตรฐาน C ++ แต่เป็น POSIX

บน MS Windows จะมี _stat, _stat64, _stati64, _wstat, _wstat64, _wstati64


1
<sys / types.h> และ <sys / stat.h> ดูmsdn.microsoft.com/en-us/library/14h5k7ff(VS.71).aspx
activout.se

1
คำตอบที่ดี +1 สำหรับการไม่ใช้ BOOSTเนื่องจากเป็นการใช้งานมากเกินไป แต่ก็ไม่สำคัญที่จะเขียนว่าจากสิ่งที่ให้ไว้ที่นี่ดังนั้นฉันจึงโพสต์คำตอบ กรุณาตรวจสอบ
gsamaras

9

แล้วไงaccess?

#include <io.h>

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

io.h normaly พร้อมใช้งานบน windows และ linux แม้ว่าจะไม่ได้มาตรฐาน?
c0m4

1
access () คือฟังก์ชัน POSIX ที่พร้อมใช้งานผ่าน <unistd.h> บน Linux
Alex B

9

ความเป็นไปได้อีกอย่างคือการใช้good()ฟังก์ชันในสตรีม:

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

7

ฉันจะพิจารณาอีกครั้งเพื่อพยายามค้นหาว่ามีไฟล์อยู่หรือไม่ คุณควรลองเปิด (ใน Standard C หรือ C ++) ในโหมดเดียวกับที่คุณต้องการใช้ สิ่งที่ใช้คือการรู้ว่ามีไฟล์อยู่หากพูดว่าไม่สามารถเขียนได้เมื่อคุณต้องการใช้งาน


จะเกิดอะไรขึ้นถ้าคุณกำลังเขียนlsโปรแกรมเหมือน? ฉันเดาว่าโปสเตอร์ต้นฉบับที่นี่ไม่ต้องการเปิดไฟล์เลย ฟังก์ชั่น stat ของ Posix ควรให้ข้อมูลเกี่ยวกับสิทธิ์ของไฟล์ดังนั้นจึงจะแก้ไขปัญหานั้นได้
Michael

6

หากคอมไพเลอร์ของคุณรองรับ C ++ 17 คุณไม่ต้องการบูสต์คุณสามารถใช้ 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

ไม่ ที่จำเป็นซึ่งจะเป็นoverkill


ใช้stat () (ไม่ใช่ข้ามแพลตฟอร์มแม้ว่า pavon จะกล่าวถึง) เช่นนี้:

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

เอาท์พุต:

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

รุ่นอื่น (และ) สามารถพบได้ที่นี่


ไม่ใช่ผู้โหวตลงคะแนน แต่เป็นคำถามที่ถามถึงโซลูชันข้ามแพลตฟอร์มและสถิติไม่มีอยู่ในทุกแพลตฟอร์ม
pavon

0

หากคุณใช้คลาสสตรีมไฟล์อินพุตอยู่แล้ว ( ifstream) คุณสามารถใช้ฟังก์ชันได้fail()ได้

ตัวอย่าง:

ifstream myFile;

myFile.open("file.txt");

// Check for errors
if (myFile.fail()) {
    cerr << "Error: File could not be found";
    exit(1);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.