Qual é a melhor maneira de verificar se existe um arquivo em C ++? (plataforma cruzada)

97

Eu li as respostas para Qual é a melhor maneira de verificar se existe um arquivo em C? (plataforma cruzada) , mas estou me perguntando se há uma maneira melhor de fazer isso usando libs c ++ padrão? De preferência, sem tentar abrir o arquivo.

Ambos state accesssão praticamente indigestíveis. O que devo #includeusar isso?

c0m4
fonte
<io.h> para acesso (que na verdade pode ser _access).
Rob
Sim, como daí apontado.
c0m4

Respostas:

170

Use boost :: filesystem :

#include <boost/filesystem.hpp>

if ( !boost::filesystem::exists( "myfile.txt" ) )
{
  std::cout << "Can't find my file!" << std::endl;
}
Andreas Magnusson
fonte
68
Parece ser um pouco complicado instalar uma enorme biblioteca de terceiros para fazer algo que deveria ser simples
c0m4
89
Boost é uma biblioteca onde muito do que eventualmente fará parte da biblioteca padrão C ++ é desenvolvido. Muitas das pessoas envolvidas com boost são pessoas envolvidas com o padrão C ++. Portanto, o boost não é apenas uma biblioteca de terceiros. Se você está programando em C ++, você deve ter instalado o boost!
Andreas Magnusson
Parece que me lembro que b :: fs :: exists retorna "true" em arquivos inexistentes em compartilhamentos de rede: "\\ machine \ share \ this_file_doesnt_exist" => true. A última vez que verifiquei foi no boost 1.33, tome cuidado ...
rlerallut
Se o seu compilador vem com uma implementação tr1, você nem precisa instalar o Boost. Estará no std :: tr1 :: filesystem
Nemanja Trifunovic
1
Na verdade, ASFAIK não fez TR1, mas será adicionado em um estágio posterior. Também não encontrei nenhuma referência a ele no rascunho oficial do TR1: open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
Andreas Magnusson
41

Tenha cuidado com as condições de corrida: se o arquivo desaparecer entre a verificação "existe" e o momento em que você o abrir, seu programa falhará inesperadamente.

É melhor abrir o arquivo, verificar se há falhas e se tudo está bem, fazer algo com o arquivo. É ainda mais importante com código crítico de segurança.

Detalhes sobre segurança e condições de corrida: http://www.ibm.com/developerworks/library/l-sprace.html

Rlerallut
fonte
30

Sou um usuário feliz e certamente usaria a solução do Andreas. Mas se você não teve acesso às bibliotecas de impulso, você pode usar a biblioteca de fluxo:

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

Não é tão bom quanto boost :: filesystem :: exists uma vez que o arquivo será realmente aberto ... mas geralmente é a próxima coisa que você quer fazer de qualquer maneira.

MattyT
fonte
15
Mas com esse código, você também pularia para a cláusula if se não tiver permissões para o arquivo, embora ele exista. Na maioria dos casos não importa, mas ainda assim vale a pena mencionar.
scigor
1
Observe que good () também resulta em true se o argumento fornecido denota um diretório, consulte stackoverflow.com/questions/9591036/…
FelixJongleur42
12

Use stat (), se for multiplataforma o suficiente para suas necessidades. Não é o padrão C ++, mas POSIX.

No MS Windows, existe _stat, _stat64, _stati64, _wstat, _wstat64, _wstati64.

activout.se
fonte
1
<sys / types.h> e <sys / stat.h> Consulte msdn.microsoft.com/en-us/library/14h5k7ff(VS.71).aspx
activout.se
1
Boa resposta +1 para NÃO USAR BOOST , já que é um exagero, no entanto, não foi trivial escrever isso com base no que é fornecido aqui, então acabei de postar uma resposta. Verifique, por favor.
gsamaras
9

Que tal access?

#include <io.h>

if (_access(filename, 0) == -1)
{
    // File does not exist
}
Roubar
fonte
O io.h está normalmente disponível no Windows e no Linux, mesmo que não seja padrão?
c0m4
1
access () é uma função POSIX que está disponível via <unistd.h> no Linux.
Alex B
9

Outra possibilidade consiste em usar a good()função no stream:

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

Eu reconsideraria tentar descobrir se existe um arquivo. Em vez disso, você deve tentar abri-lo (em C padrão ou C ++) no mesmo modo em que pretende usá-lo. Qual a utilidade de saber que o arquivo existe se, digamos, não for gravável quando você precisa usá-lo?

fizzer
fonte
E se você estiver escrevendo um lsprograma semelhante? Suponho que o autor da postagem original não deseja abrir o arquivo de forma alguma. A função stat do Posix supostamente fornece informações sobre as permissões do arquivo, portanto, resolveria o problema.
Michael
6

Se o seu compilador suporta C ++ 17, você não precisa de impulso, você pode simplesmente usar std::filesystem::exists

#include <iostream> // only for std::cout
#include <filesystem>

if (!std::filesystem::exists("myfile.txt"))
{
    std::cout << "File not found!" << std::endl;
}
AlbertM
fonte
3

NÃO REQUERIDO , o que seria um exagero .


Use stat () (não plataforma cruzada, embora conforme mencionado por pavon), assim:

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

Resultado:

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

Outra versão (e essa) pode ser encontrada aqui .

gsamaras
fonte
Não o downvoter, mas a pergunta feita para uma solução de plataforma cruzada, e stat não existe em todas as plataformas.
pavon de
0

Se você já estiver usando a classe de fluxo de arquivo de entrada ( ifstream), poderá usar sua função fail().

Exemplo:

ifstream myFile;

myFile.open("file.txt");

// Check for errors
if (myFile.fail()) {
    cerr << "Error: File could not be found";
    exit(1);
}
Reza Saadati
fonte