Gostaria de encontrar a maneira mais rápida de verificar se existe um arquivo no padrão C ++ 11, C ++ ou C. Tenho milhares de arquivos e antes de fazer algo neles preciso verificar se todos eles existem. O que posso escrever em vez de /* SOMETHING */
na seguinte função?
inline bool exist(const std::string& name)
{
/* SOMETHING */
}
boost::filesystem
parece usarstat()
. (Assumindo a partir da documentação.) Não acho que você possa fazer muito mais rápido para chamadas de FS. A maneira de acelerar o que você está fazendo é "evitar a visualização de milhares de arquivos".git push
provavelmente não se preocupa em garantir que você não esteja tocando na árvore de trabalho após a verificação inicial suja.Respostas:
Bem, juntei um programa de teste que executou cada um desses métodos 100.000 vezes, metade em arquivos que existiam e metade em arquivos que não existiam.
Resultados do tempo total para executar as 100.000 chamadas em média em 5 execuções,
A
stat()
função forneceu o melhor desempenho no meu sistema (Linux, compilado comg++
), com umafopen
chamada padrão sendo sua melhor aposta se, por algum motivo, se recusar a usar as funções POSIX.fonte
stat()
parece verificar a existência.f.close()
pois f sai do escopo no final da função. Então,return f.good()
poderia substituir oif
bloco?Observação: no C ++ 14 e assim que o TS do sistema de arquivos for concluído e adotado, a solução será usar:
e desde C ++ 17, apenas:
fonte
std::tr2::sys::exists("helloworld.txt");
std::exists
, isso seria bastante confuso (pense: existe em um contêiner STL como um conjunto).#include <experimental/filesystem> bool file_exists(std::string fn) { std::experimental::filesystem::exists("helloworld.txt"); }
#include <experimental/filesystem>
Eu uso esse pedaço de código, ele funciona bem comigo até agora. Isso não usa muitos recursos sofisticados do C ++:
fonte
ifstream
destruidor será chamado ao sairis_file_exist
e fechará o fluxo.return std::ifstream(fileName);
Depende de onde os arquivos residem. Por exemplo, se todos eles deveriam estar no mesmo diretório, você pode ler todas as entradas do diretório em uma tabela de hash e depois verificar todos os nomes na tabela de hash. Isso pode ser mais rápido em alguns sistemas do que verificar cada arquivo individualmente. A maneira mais rápida de verificar cada arquivo individualmente depende do seu sistema ... se você estiver escrevendo ANSI C, a maneira mais rápida é
fopen
porque é a única maneira (um arquivo pode existir, mas não pode ser aberto, mas você provavelmente realmente deseja abrir se você precisa "fazer algo nele"). C ++, POSIX, Windows oferecem opções adicionais.Enquanto estou nisso, deixe-me apontar alguns problemas com sua pergunta. Você diz que deseja o caminho mais rápido e possui milhares de arquivos, mas solicita o código de uma função para testar um único arquivo (e essa função é válida apenas em C ++, não em C). Isso contradiz seus requisitos, assumindo a solução ... um caso do problema XY . Você também diz "no padrão c ++ 11 (ou) c ++ (ou) c" ... que são todos diferentes, e isso também é inconsistente com o seu requisito de velocidade ... a solução mais rápida envolveria a adaptação do código ao sistema de destino. A inconsistência na pergunta é destacada pelo fato de você ter aceitado uma resposta que fornece soluções que dependem do sistema e não são C ou C ++ padrão.
fonte
Para quem gosta de impulso:
fonte
Sem usar outras bibliotecas, eu gosto de usar o seguinte trecho de código:
Isso funciona em várias plataformas para sistemas compatíveis com Windows e POSIX.
fonte
unistd.h
também. Talvez o primeiro#ifdef
deva ser específico do Windows?O mesmo que sugerido por PherricOxide, mas em C
fonte
fonte
close()
não é necessário.Outras 3 opções no Windows:
1
2
3
fonte
GetFileAttributes
versão é basicamente a maneira canônica de fazer isso no Windows.Você também pode fazer
bool b = std::ifstream('filename').good();
. Sem as instruções de ramificação (como se), ele deve ter um desempenho mais rápido, pois precisa ser chamado milhares de vezes.fonte
Se você precisar distinguir entre um arquivo e um diretório, considere o seguinte: ambos usam stat, que é a ferramenta padrão mais rápida, conforme demonstrado pelo PherricOxide:
fonte
Eu preciso de uma função rápida que possa verificar se um arquivo existe ou não e a resposta do PherricOxide é quase o que eu preciso, exceto que não compara o desempenho das funções boost :: filesystem :: existentes e abertas. A partir dos resultados do benchmark, podemos ver facilmente que:
Usar a função stat é a maneira mais rápida de verificar se existe um arquivo. Observe que meus resultados são consistentes com os da resposta do PherricOxide.
O desempenho da função boost :: filesystem :: existe é muito próximo ao da função stat e também é portátil. Eu recomendaria esta solução se as bibliotecas de impulso estiverem acessíveis no seu código.
Resultados de benchmark obtidos com o kernel Linux 4.17.0 e gcc-7.3:
Abaixo está o meu código de referência:
fonte
Você pode usar
std::ifstream
, comois_open
,fail
por exemplo, o código abaixo (o cout "aberto" significa que o arquivo existe ou não):citado nesta resposta
fonte
onde
R
está a sua sequência de coisas semelhantes a caminhos eexists()
é a partir do futuro std ou atual impulso. Se você criar o seu próprio, seja simples,A solução ramificada não é absolutamente terrível e não devora os descritores de arquivos,
fonte
PathFileExists
está limitado aMAX_PATH
(260) caracteres;GetFileAttributes
não tem essa limitação.GetFileAttributes
também está limitado a MAX_PATH. Os documentos descrevem uma solução alternativa se você usar caminhos absolutos, unicode e acrescentar uma sequência de prefixos especial ao nome do caminho. Acho que estamos de acordo com as respostas específicas do Windows.GetFileAttributesW
não tem a limitação.No C ++ 17:
fonte
Usando o MFC, é possível com os seguintes
Onde
FileName
está uma string representando o arquivo que você está verificando quanto à existênciafonte
existe apenas uma maneira mais rápida de verificar se o arquivo existe e se você tem permissão para lê-lo da maneira que está usando a linguagem C, o desejo é mais rápido e pode ser usado também em qualquer versão do C ++
solução : em C, há uma biblioteca errno.h que possui uma variável inteira (global) externa chamada errno, que contém um número que pode ser usado para reconhecer o tipo de erro
fonte
Embora existam várias maneiras de fazer isso, a solução mais eficiente para o seu problema provavelmente seria usar um dos métodos predefinidos do fstream, como good () . Com esse método, você pode verificar se o arquivo especificado existe ou não.
Espero que você ache isso útil.
fonte