std::ofstream, проверете дали файлът съществува преди запис

Внедрявам функция за запазване на файлове в приложение Qt, използвайки C++.

Търся начин да проверя дали избраният файл вече съществува, преди да пиша в него, така че да мога да изпратя предупреждение към потребителя.

Използвам std::ofstream и не търся решение за Boost.


person cweston    schedule 30.11.2010    source източник
comment
Възможни дублирани въпроси: stackoverflow.com/questions/1383617/, stackoverflow.com/questions/574285/, stackoverflow.com/questions/268023/   -  person Brent Writes Code    schedule 30.11.2010
comment
добавете копие: stackoverflow.com/questions/12774207/   -  person zhangxaochen    schedule 04.04.2016


Отговори (6)


Това е една от любимите ми функции за прибиране, които държа под ръка за многократна употреба.

#include <sys/stat.h>
// Function: fileExists
/**
    Check if a file exists
@param[in] filename - the name of the file to check

@return    true if the file exists, else false

*/
bool fileExists(const std::string& filename)
{
    struct stat buf;
    if (stat(filename.c_str(), &buf) != -1)
    {
        return true;
    }
    return false;
}

Намирам това за много по-вкусно, отколкото да се опитвате да отворите файл, ако нямате непосредствени намерения да го използвате за I/O.

person Rico    schedule 09.06.2011
comment
+1 за пример с използване на stat вместо отваряне на файл само за да го затворите. - person Chris Smith; 10.06.2011
comment
+1, но return stat(filename.c_str(), &buf) != 1; е доста по-компактен. - person Matt Phillips; 14.03.2013
comment
Измерих тези на 2,67GHz Intel Xeon. Методът за статистика по-горе отне 0,93 микросекунди, за да потвърди, че файл от 500 MB съществува. Методите на ifstream по-долу отнеха 17,4 микросекунди на същия файл. За да се каже, че не съществува файл, stat отне 0,72 микросекунди, ifstream отне 2,4 микросекунди. - person Schroeder; 02.04.2013
comment
@MattPhillips: Но това не изглежда да има желания ефект. - person Steve; 26.11.2013
comment
@Steve: Освен факта, че кодът на Мат Филипс не декларира структурата (предполагам, че е имал предвид, че се подразбира) и факта, че той използва != 1 вместо != -1, защо да няма същия ефект? - person Gurgadurgen; 04.05.2014
comment
Мисля, че имаше предвид bool fileExists(const std::string& filename) { struct stat buf; return (stat(filename.c_str(), &buf) != -1); } - person Kong Chun Ho; 12.01.2017
comment
Има ли причина за използването на ключовата дума struct? Не е необходимо в C++, освен ако има някакъв конфликт на имена в заглавката на C, за който не знам? - person Lightness Races in Orbit; 03.03.2017

bool fileExists(const char *fileName)
{
    ifstream infile(fileName);
    return infile.good();
}

Този метод досега е най-краткият и най-преносимият. Ако употребата не е много сложна, това е едно, което бих избрал. Ако искате също да изведете предупреждение, бих го направил основно.

person return 0    schedule 15.06.2012
comment
Обяснение: Използва конструктора ifstream, за да се опита да отвори файла за четене. Когато функцията се върне и ifstream излезе извън обхвата, нейният деструктор ще затвори имплицитно файла (в случай, че файлът е съществувал и отварянето е успешно). - person grubs; 02.07.2014
comment
Освен че прави грешното нещо: проверява дали даден файл може да бъде отворен, а не дали съществува. Ако разрешенията за достъп забраняват на потребителя достъп до него, тази функция погрешно ще твърди, че файлът не съществува, защото няма да може да го отвори за четене. - person SasQ; 16.02.2019

fstream file;
file.open("my_file.txt", ios_base::out | ios_base::in);  // will not create file
if (file.is_open())
{
    cout << "Warning, file already exists, proceed?";
    if (no)
    { 
        file.close();
        // throw something
    }
}
else
{
    file.clear();
    file.open("my_file.txt", ios_base::out);  // will create if necessary
}

// do stuff with file

Имайте предвид, че в случай на съществуващ файл, това ще го отвори в режим на произволен достъп. Ако предпочитате, можете да го затворите и да го отворите отново в режим на добавяне или съкращаване.

person HighCommander4    schedule 09.06.2011
comment
Помислете какво би се случило, ако файлът съществува, но потребителят няма права за достъп, за да го прочете. - person SasQ; 16.02.2019
comment
@SasQ: Да... това определено е хак/заобиколно решение. Правилното решение в C++17 е std::filesystem::exists() или като изключим това, stat() . - person HighCommander4; 24.02.2019

Опитайте ::stat() (декларирано в <sys/stat.h>)

person NPE    schedule 30.11.2010

Един от начините би бил да направите stat() и да проверите errno.
Примерен код ще изглежда така:

#include <sys/stat.h>
using namespace std;
// some lines of code...

int fileExist(const string &filePath) {
    struct stat statBuff;
    if (stat(filePath.c_str(), &statBuff) < 0) {
        if (errno == ENOENT) return -ENOENT;
    }
    else
        // do stuff with file
}

Това работи независимо от потока. Ако все пак предпочитате да проверявате с ofstream, просто проверете с is_open().
Пример:

ofstream fp.open("<path-to-file>", ofstream::out);
if (!fp.is_open()) 
    return false;
else 
    // do stuff with file

Надявам се това да помогне. Благодаря!

person Bhagyesh Dudhediya    schedule 30.07.2016

С std::filesystem::exists от C++17:

#include <filesystem> // C++17
#include <iostream>
namespace fs = std::filesystem;

int main()
{
    fs::path filePath("path/to/my/file.ext");
    std::error_code ec; // For using the noexcept overload.
    if (!fs::exists(filePath, ec) && !ec)
    {
        // Save to file, e.g. with std::ofstream file(filePath);
    }
    else
    {
        if (ec)
        {
            std::cerr << ec.message(); // Replace with your error handling.
        }
        else
        {
            std::cout << "File " << filePath << " does already exist.";
            // Handle overwrite case.
        }
    }
}

Вижте също std::error_code.

В случай, че искате да проверите дали пътят, в който пишете, всъщност е обикновен файл, използвайте std::filesystem::is_regular_file.

person Roi Danton    schedule 18.06.2018