web-dev-qa-db-fra.com

std :: ofstream, vérifiez si le fichier existe avant d'écrire

J'implémente la fonctionnalité d'enregistrement de fichiers dans une application Qt utilisant C++.

Je cherche un moyen de vérifier si le fichier sélectionné existe déjà avant d'y écrire, afin que je puisse demander un avertissement à l'utilisateur.

J'utilise un std::ofstream et je ne cherche pas une solution Boost.

33
cweston

C'est l'une de mes fonctions préférées que je garde à portée de main pour de multiples utilisations.

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

Je trouve cela beaucoup plus de bon goût que d'essayer d'ouvrir un fichier si vous n'avez pas l'intention immédiate de l'utiliser pour les E/S.

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

Cette méthode est jusqu'à présent la plus courte et la plus portable. Si l'utilisation n'est pas très sophistiquée, c'est celle que j'opterais. Si vous souhaitez également demander un avertissement, je le ferais principalement.

38
return 0
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

Notez que dans le cas d'un fichier existant, cela l'ouvrira en mode d'accès aléatoire. Si vous préférez, vous pouvez le fermer et le rouvrir en mode ajout ou en mode tronqué.

9
HighCommander4

Essayez ::stat() (déclaré dans <sys/stat.h>)

4
NPE

Une des façons serait de faire stat() et de vérifier errno.
Un exemple de code ressemblerait à ceci:

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

Cela fonctionne indépendamment du flux. Si vous préférez toujours vérifier en utilisant ofstream vérifiez simplement en utilisant is_open().
Exemple:

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

J'espère que cela t'aides. Merci!

2
Bhagyesh Dudhediya

Avec std::filesystem::exists de 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.
        }
    }
}

Voir également std::error_code .

Si vous souhaitez vérifier si le chemin d'accès vers lequel vous écrivez est bien un fichier normal, utilisez std::filesystem::is_regular_file .

1
Roi Danton