HOWTO · Csharp

Verifique se existe um arquivo em C#

O método File.Exists() pode ser usado para verificar se um arquivo existe em um caminho específico em C#.

Nesta página

Antes de o programa ler, gravar ou excluir um arquivo, muitas vezes ajuda saber se ele realmente está lá. O C# oferece essa verificação por meio de File.Exists, um método do namespace System.IO que testa um caminho e retorna uma resposta booleana. Este guia mostra como chamá-lo, como caminhos relativos e absolutos determinam o que é verificado, o que um resultado false realmente informa e como agir com base na resposta sem confiar nela além do devido.

Verifique se um arquivo existe com File.Exists

File.Exists é um método estático, portanto você o chama na própria classe File, e não em uma instância. Você passa um caminho como uma string, e ele retorna true quando o sistema operacional consegue confirmar um arquivo regular nesse caminho e false quando não consegue.

Execute este exemplo:

O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string path = Path.Combine(Path.GetTempPath(), "delftstack-demo.txt");
        File.WriteAllText(path, "demo content");
        bool fileExists = File.Exists(path);
        Console.WriteLine($"Does the file exist? {fileExists}");
        File.Delete(path);
    }
}

Saída:

Does the file exist? True

O programa cria um arquivo pequeno no diretório temporário do sistema, pergunta sobre ele a File.Exists e imprime a resposta, que é True porque o arquivo acabou de ser criado. Aponte path para o local que você precisar testar; a chamada permanece a mesma e o resultado é sempre um bool simples, pronto para uma instrução if ou para ser guardado em uma variável.

Escolha o caminho a verificar

A string que você passa determina qual local será examinado, portanto escolha-a com cuidado.

Um caminho absoluto identifica o arquivo por completo — C:\Data\report.txt no Windows ou /var/data/report.txt no Linux. Ele se refere ao mesmo local, não importa de onde o programa seja executado, portanto dê preferência a ele quando o local for fixo ou vier da configuração ou da entrada do usuário.

Um caminho relativo como report.txt ou logs/report.txt é resolvido em relação ao diretório de trabalho do processo, o valor de Environment.CurrentDirectory. Normalmente é a pasta em que o processo foi iniciado — não necessariamente a pasta que contém o executável — e outro código pode alterá-lo, portanto um caminho relativo pode apontar silenciosamente para um local diferente do esperado.

Execute este exemplo para ver o mesmo nome relativo resolver para dois lugares diferentes:

O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string dir = Path.Combine(Path.GetTempPath(), "delftstack-cwd-demo");
        Directory.CreateDirectory(dir);
        File.WriteAllText(Path.Combine(dir, "delftstack-report-7f3a1c.txt"), "demo");

        Console.WriteLine(File.Exists("delftstack-report-7f3a1c.txt"));

        Directory.SetCurrentDirectory(dir);
        Console.WriteLine(File.Exists("delftstack-report-7f3a1c.txt"));

        Directory.SetCurrentDirectory(Path.GetTempPath());
        File.Delete(Path.Combine(dir, "delftstack-report-7f3a1c.txt"));
        Directory.Delete(dir);
    }
}

Saída:

False
True

A primeira verificação procura o arquivo no diretório de trabalho original e não encontra nada. Depois que Directory.SetCurrentDirectory move o processo para a pasta que contém o arquivo, o mesmo nome relativo resolve para ele e a verificação retorna True.

Ao escrever caminhos do Windows em código-fonte C#, a barra invertida exige atenção apenas por causa da sintaxe de string, não porque o Windows exija separadores duplicados. Em uma string comum, \ inicia uma sequência de escape, portanto escreva "C:\\Data\\report.txt"; em uma string verbatim prefixada com @, escreva barras invertidas simples: @"C:\Data\report.txt". O .NET também aceita barras normais ("C:/Data/report.txt") no Windows e, no Linux e no macOS, / é o separador normal, portanto Path.Combine é a maneira mais portátil de montar caminhos.

Interprete o resultado e suas limitações

File.Exists responde a uma pergunta restrita: o sistema operacional consegue confirmar um arquivo neste caminho agora? Leia false como “não foi possível confirmar”, e não especificamente como “o arquivo está ausente”. O método também retorna false quando o caminho é null ou malformado, quando o caminho nomeia um diretório em vez de um arquivo (use Directory.Exists para pastas) e quando a própria verificação encontra problemas, como falta de permissão para percorrer as pastas.

Esses problemas são absorvidos pelo resultado false em vez de serem lançados, portanto um try/catch em torno de File.Exists quase nunca observará nada. Se o programa precisar saber por que um caminho falhou — para registrar, avisar o usuário ou decidir se deve tentar novamente — verifique você mesmo a condição específica ou simplesmente tente a operação real no arquivo e leia o erro que ela relata.

A chamada é síncrona e acessa o sistema de arquivos. Normalmente isso é rápido, mas pode demorar de forma perceptível em um compartilhamento de rede ou em um disco lento, portanto evite chamá-la em um loop apertado quando um único resultado armazenado for suficiente.

Use o resultado com segurança

Trate a resposta como um instantâneo, não como uma garantia. Entre a chamada a File.Exists e o momento em que você abre o arquivo, outro processo — ou outra thread do próprio programa — pode excluí-lo, movê-lo ou substituí-lo, e até if (File.Exists(path)) File.ReadAllText(path) ainda pode falhar.

O hábito robusto é agir sobre o arquivo e tratar o resultado da própria operação:

O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string path = Path.Combine(Path.GetTempPath(), "delftstack-read-demo.txt");
        File.WriteAllText(path, "hello from disk");

        if (File.Exists(path))
        {
            try
            {
                Console.WriteLine(File.ReadAllText(path));
            }
            catch (IOException)
            {
                Console.WriteLine("The file could not be read.");
            }
            catch (UnauthorizedAccessException)
            {
                Console.WriteLine("Access to the file was denied.");
            }
        }

        File.Delete(path);
    }
}

Saída:

hello from disk

Aqui File.Exists evita o trabalho de forma limpa quando não há nada, enquanto o try/catch em torno de File.ReadAllText cobre o que a verificação não consegue — um arquivo que desapareceu (manifestado como FileNotFoundException, um tipo de IOException), um arquivo bloqueado por outro processo ou acesso negado. Quando seu único objetivo é ler o arquivo, você pode dispensar a verificação e deixar o catch tratar a ausência, o que elimina totalmente a condição de corrida. Mantenha File.Exists para decisões em que a resposta booleana basta por si só: exibir uma mensagem, escolher entre criar e abrir um arquivo ou pular uma etapa de limpeza.