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

Я считаю это гораздо более вкусным, чем пытаться открыть файл, если у вас нет непосредственных намерений использовать его для ввода-вывода.

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
Я рассчитал их на Intel Xeon с тактовой частотой 2,67 ГГц. Вышеупомянутому статистическому методу потребовалось 0,93 микросекунды для подтверждения существования файла размером 500 МБ. Приведенные ниже методы 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
Explanation: Использует конструктор 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