CodeGym /Cursos /C# SELF /Trabalhando com arquivos em C#: classe

Trabalhando com arquivos em C#: classe System.IO.File

C# SELF
Nível 35 , Lição 2
Disponível

1. Classe File: simplicidade e eficiência

A classe System.IO.File segue a ideia de "uma operação — um método". Ela oferece um monte de métodos de alto nível que escondem toda a treta de lidar com o sistema operacional, deixando você focar só no que interessa.

O que exatamente a classe File faz?

  • Grava texto ou dados binários aleatórios em um arquivo.
  • Lê o conteúdo de um arquivo inteiro ou linha por linha (para arquivos de texto).
  • Copia, deleta e renomeia arquivos existentes.
  • Verifica se um arquivo existe em um caminho específico.
  • Trabalha com atributos do arquivo (tipo data de criação, tamanho – usando outras classes).

Por que isso é prático?
Todos os métodos do File são estáticos. Ou seja, não precisa criar objeto nenhum, só chamar o método que você quer, tipo:

File.WriteAllText("data.txt", "Oi, arquivo!");

Esse estilo lembra muito o uso da classe Console: tudo simples e direto, sem precisar "instanciar" nada, sem se preocupar com streams.

Se você quer uma ferramenta universal e fácil pra mexer com arquivos, a classe System.IO.File é perfeita. Ela tem métodos pra ler, gravar, copiar, deletar e outras operações básicas, tipo um canivete suíço do sistema de arquivos.

Como usar File?

Todos os métodos da classe File são estáticos, então não precisa criar objeto nenhum — só manda um File.AlgumaCoisa(). É igualzinho chamar Console.WriteLine(), só que agora é pra arquivos.

string text = "Oi, mundo!";
string path = "hello.txt";

// Grava texto no arquivo (se já existir, sobrescreve!)
File.WriteAllText(path, text);

// Lê o arquivo inteiro numa string só
string readText = File.ReadAllText(path);

Console.WriteLine("Conteúdo do arquivo: " + readText);

Dica: Se você tá usando ReadAllText e WriteAllText toda hora, provavelmente tá fazendo algo errado — esses métodos são bons pra cenários simples e arquivos pequenos.

Métodos mais usados da classe File

Método Descrição
File.Exists(path)
Verifica se o arquivo existe no caminho informado
File.Delete(path)
Deleta o arquivo
File.Copy(src, dest)
Copia o arquivo
File.Move(src, dest)
Move (ou renomeia) o arquivo
File.ReadAllText(path)
Lê o arquivo inteiro como uma string só
File.WriteAllText(path, t)
Grava uma string no arquivo (sobrescreve se já existir)
File.ReadAllLines(path)
Lê todas as linhas do arquivo num array de strings
File.WriteAllLines(path, a)
Grava um array de strings no arquivo (cada string vira uma linha)
File.ReadAllBytes(path)
Lê todos os bytes do arquivo num array de bytes
File.WriteAllBytes(path, b)
Grava um array de bytes no arquivo

2. Gravando e lendo arquivos de texto

Bora ver os métodos mais usados da classe File com exemplos práticos. Pra usar eles, sempre coloca using System.IO; no começo do seu arquivo de código.

using System;
using System.IO; // Necessário pra usar a classe File
using System.Linq; // Pode precisar pra ReadLines

Lendo o arquivo inteiro

Essa é uma das tarefas mais comuns: salvar dados de texto num arquivo ou carregar eles de volta.

Gravar uma linha (ou todo o texto) no arquivo: File.WriteAllText() Esse método cria um novo arquivo no caminho informado. Se já existir um arquivo com esse nome, o conteúdo dele vai ser totalmente sobrescrito pelo novo texto.

string myFilePath = "notes.txt";
string textContent = "Hoje é um ótimo dia pra aprender C#.\nNão esquece de fazer o dever de casa.";

// Grava todo o texto no arquivo
File.WriteAllText(myFilePath, textContent); 
Console.WriteLine($"Arquivo '{myFilePath}' criado/sobrescrito com sucesso.");

Ler o arquivo inteiro numa string só: File.ReadAllText() Esse método lê todo o conteúdo do arquivo de texto do começo ao fim e retorna tudo numa string grandona.

string myFilePath = "notes.txt";

// Importante: sempre verifica se o arquivo existe antes de ler, pra não dar erro!
if (File.Exists(myFilePath))
{
    string content = File.ReadAllText(myFilePath);
    Console.WriteLine($"Conteúdo do arquivo '{myFilePath}':\n{content}");
}
else
{
    Console.WriteLine($"Erro: Arquivo '{myFilePath}' não encontrado pra leitura.");
}

Observação importante: Os métodos File.WriteAllText() e File.ReadAllText() são ótimos pra arquivos pequenos e médios (tipo notas, arquivos de config, logs curtos). Mas se o arquivo for muito grande (dezenas ou centenas de megas, ou até gigas), carregar tudo numa string só pode gastar muita memória e até causar OutOfMemoryException. Pra esses casos, existem jeitos mais eficientes (vou falar disso já já e nas próximas aulas).

3. Lendo arquivo linha por linha

Quando você tá lidando com arquivos de texto grandes, tipo relatórios CSV enormes, logs gigantes ou bancos de dados em texto, ler tudo de uma vez pra memória (ou seja, carregar o arquivo inteiro do disco pra RAM) não é eficiente e pode nem ser possível. Aí entra o File.ReadLines().

File.ReadLines(path) — esse método não carrega o arquivo inteiro de uma vez. Ele retorna uma coleção especial (IEnumerable<string>) que deixa você ler o arquivo linha por linha, só quando precisar. Isso é chamado de "leitura preguiçosa" ou "leitura em streaming".

string logFilePath = "application.log";
string text = """
INFO: Aplicativo iniciado.
WARN: Problema detectado no módulo X.
ERROR: Erro crítico de rede.
INFO: Aplicativo finalizado.    
""";    
    
// Suponha que temos um arquivo de log com várias linhas.
File.WriteAllText(logFilePath, text);

// Cada volta do loop lê e processa SÓ UMA linha 
foreach (string line in File.ReadLines(logFilePath))
    Console.WriteLine($"- {line}");

Vantagem: O arquivo é lido e processado aos poucos, o que economiza muita memória quando você trabalha com arquivos grandes.

Diferença entre File.ReadLines() e File.ReadAllLines():

  • File.ReadAllLines(path): Carrega todas as linhas do arquivo de uma vez pra memória e retorna um array string[]. Depois de chamar esse método, o arquivo inteiro já tá na RAM. É útil se você precisa acessar todas as linhas ao mesmo tempo (tipo pra ordenar ou buscar).
  • File.ReadLines(path): Retorna um IEnumerable<string>, que deixa você percorrer as linhas uma a uma. O arquivo só é lido quando você pede a próxima linha (tipo num foreach). Isso é mais eficiente pra arquivos muito grandes, quando não dá ou não faz sentido carregar tudo pra memória.

4. Gravando um array de strings

Às vezes você tem uma lista de strings (tipo de uma coleção) e quer gravar cada string como uma linha separada no arquivo.

File.WriteAllLines(path, contents)

Esse método recebe um array de strings (ou qualquer coleção de strings) e grava cada string como uma linha separada no arquivo. Igual ao WriteAllText(), ele sobrescreve o arquivo se já existir.

string membersFilePath = "participants.txt";
string[] names = { "Ivan Petrov", "Maria Sidorova", "Sergey Kozlov", "Anna Kuznetsova" };

// Cada string do array vira uma linha no arquivo
File.WriteAllLines(membersFilePath, names);

// Vamos conferir o conteúdo
Console.WriteLine($"Conteúdo de '{membersFilePath}':");
foreach (string line in File.ReadLines(membersFilePath))
    Console.WriteLine($"- {line}");

5. Trabalhando com arquivos binários

A classe File não serve só pra texto. Ela também tem métodos práticos pra ler e gravar dados binários, ou seja, bytes crus. Isso é útil, por exemplo, pra salvar configs em formato próprio, mexer com imagens, áudio ou qualquer dado que não seja texto puro.

Gravar um array de bytes: File.WriteAllBytes() Cria ou sobrescreve um arquivo, gravando nele todo o array de bytes que você passar.

string binaryDataPath = "settings.bin";
// Exemplo de dados binários: imagem, vídeo, qualquer coisa
byte[] settingsData = { 0x01, 0x0A, 0x2C, 0xFF, 0x00, 0x3F }; // Uns "settings" crus

File.WriteAllBytes(binaryDataPath, settingsData);
Console.WriteLine($"Dados binários gravados no arquivo '{binaryDataPath}'.");

Importante: se você tentar abrir 'settings.bin' no Bloco de Notas, vai ver um monte de símbolos estranhos, porque esses bytes não são texto.

Ler um array de bytes: File.ReadAllBytes() Lê todo o conteúdo do arquivo binário pra um array de bytes.

if (File.Exists(binaryDataPath))
{
    byte[] readSettings = File.ReadAllBytes(binaryDataPath);
    Console.WriteLine($"Lidos {readSettings.Length} bytes do arquivo '{binaryDataPath}'.");

    Console.Write("Bytes lidos (em hexadecimal): ");
    foreach (byte b in readSettings)
        Console.Write($"{b:X2} "); // :X2 formata o byte como dois dígitos hexadecimais

    Console.WriteLine();
}
else
{
    Console.WriteLine($"Erro: Arquivo binário '{binaryDataPath}' não encontrado.");
}

Esses métodos são ótimos pra salvar pequenos pedaços de dados binários, tipo cache de imagens pequenas ou objetos serializados.

6. Gerenciando arquivos no disco

A classe File também tem métodos pra gerenciar arquivos no disco.

Verificar se o arquivo existe: File.Exists(path) Retorna true se o arquivo existe no caminho informado, e false se não. Sempre bom usar esse método antes de tentar ler, deletar ou fazer qualquer coisa que pode dar erro se o arquivo não existir.

string myFileToCheck = "report.txt";
// Primeiro vamos criar ele só pra exemplo
File.WriteAllText(myFileToCheck, "Relatório de teste.");

if (File.Exists(myFileToCheck))
{
    Console.WriteLine($"Arquivo '{myFileToCheck}' encontrado.");
    // Agora pode ler, deletar, etc, sem medo
}
else
{
    Console.WriteLine($"Arquivo '{myFileToCheck}' não encontrado.");
}

Deletar arquivo: File.Delete(path) apaga o arquivo do disco pra sempre. Cuidado, isso não tem volta!

string fileToDelete = "temp_file.txt";
// Vamos criar o arquivo pra exemplo
File.WriteAllText(fileToDelete, "Esse arquivo vai ser deletado.");

if (File.Exists(fileToDelete))
{
    File.Delete(fileToDelete);
    Console.WriteLine($"Arquivo '{fileToDelete}' deletado com sucesso.");
}
else
{
    Console.WriteLine($"Arquivo '{fileToDelete}' já não existe ou foi deletado antes.");
}

7. Exceções ao trabalhar com arquivos

Mexer com arquivos sempre envolve lidar com o sistema operacional e recursos externos, então pode dar ruim de várias formas.

Trate as exceções (erros)! Quando você mexe com arquivos, pode acontecer um monte de coisa errada, e seu programa tem que saber lidar com isso, não só "quebrar". Exemplos comuns:

  • FileNotFoundException: O arquivo que você tentou acessar não existe no caminho informado.
  • DirectoryNotFoundException: A pasta onde você tentou criar ou achar o arquivo não existe.
  • UnauthorizedAccessException: Seu programa não tem permissão pra ler, gravar ou deletar o arquivo/pasta (tipo arquivo do sistema ou área protegida).
  • IOException: Erro geral de entrada/saída, geralmente quando o arquivo já tá aberto em outro programa e bloqueado, ou não tem espaço no disco.

Sempre use try-catch pra trabalhar com arquivos de forma segura. Assim você "pega" o erro e pode tomar uma atitude (tipo mostrar mensagem pro usuário, gravar no log, etc).

string sensitiveFilePath = "secret_data.txt";

try
{
    // Tentando ler um arquivo que pode não existir ou não ter permissão
    string secretContent = File.ReadAllText(sensitiveFilePath);
    Console.WriteLine($"Conteúdo secreto lido: {secretContent}");
}
catch (FileNotFoundException) // Erro específico: arquivo não encontrado
{
    Console.WriteLine($"Erro: Arquivo '{sensitiveFilePath}' não encontrado. Confere se o caminho tá certo.");
}
catch (IOException ex) // Erro geral de I/O (tipo arquivo bloqueado)
{
    Console.WriteLine($"Erro de entrada/saída ao mexer com o arquivo '{sensitiveFilePath}': {ex.Message}");
}
catch (Exception ex) // Qualquer outro erro inesperado
{
    Console.WriteLine($"Erro inesperado: {ex.Message}");
}

8. Quando System.IO.File não é a melhor escolha?

Apesar da classe File ser super versátil, tem situações em que ela não é a melhor opção ou nem funciona:

Arquivos gigantes (dezenas+ de gigas): Os métodos ReadAllText()/ReadAllBytes() carregam o arquivo inteiro pra memória. Pra arquivos enormes, isso vai dar OutOfMemoryException. Nesses casos, use File.ReadLines() (pra texto) ou trabalhe direto com streams (FileStream) pra ler/gravar aos pedaços. (Streams é assunto pra próxima aula).

Controle fino de acesso ao arquivo: Se você precisa de controle bem específico de como o arquivo é aberto (tipo acesso exclusivo, pra ninguém mais ler ou gravar, ou acesso simultâneo de vários processos), File não oferece esse nível de detalhe. Pra isso, tem que usar classes de stream mais baixas.

Operações assíncronas: Pra apps de alta performance, que precisam fazer operações de arquivo sem travar a thread principal (tipo servidores web), precisa de métodos assíncronos (tipo ReadAllTextAsync()), que também usam streams por baixo.

Leitura/gravação parcial: Se você quer ler só uma parte do arquivo a partir de um offset ou gravar dados no meio de um arquivo já existente, os métodos do File não servem. Tem que usar acesso direto ao stream do arquivo.

9. Resumão

Por que System.IO.File faz tanto sucesso?

  • Simplicidade e clareza: Os métodos estáticos permitem fazer operações complexas em uma ou duas linhas. Isso deixa o código mais limpo e fácil de entender.
  • Gerenciamento automático de recursos: File cuida de abrir e fechar arquivos pra cada operação, então você não precisa se preocupar com isso (e evita muitos bugs).
  • Serve pra quase tudo do dia a dia: Pra maioria das tarefas com arquivos de texto e binários pequenos ou médios, o File resolve tranquilo.
  • É padrão: Na maioria dos projetos e entrevistas, esperam que você saiba usar os métodos da classe File sem medo.
  • Complexidade escondida: Todos os métodos são feitos pra esconder a treta de lidar com o sistema operacional, deixando só uma interface limpa e fácil pra você.

Perguntas Frequentes e Dúvidas

Qual o tamanho máximo de arquivo que dá pra usar com File.ReadAllText()?
Pra arquivos de até algumas dezenas de megas (< 100 MB) normalmente não tem problema. Se o arquivo for maior (centenas de MB, gigas), usar File.ReadAllText() pode acabar com a memória RAM (vai dar OutOfMemoryException). Nesses casos, use File.ReadLines() pra ler linha por linha ou ferramentas mais avançadas pra processamento em streaming, que você vai aprender depois.

Dá pra criar/gravar arquivo numa pasta que não existe?
Não. Os métodos File.WriteAllText(), File.WriteAllBytes() e outros não criam as pastas automaticamente. Se você passar um caminho tipo C:\MyAppData\Logs\current.log e as pastas MyAppData ou Logs não existirem, vai dar DirectoryNotFoundException. Primeiro, garanta que todas as pastas existem, usando métodos da classe System.IO.Directory (tipo Directory.CreateDirectory("myfolder")).

Como saber a data de criação, modificação ou o tamanho do arquivo?
Pra pegar informações detalhadas do arquivo, tipo data de criação, última modificação, tamanho, atributos (oculto, somente leitura, etc), use a classe System.IO.FileInfo. Ela tem várias propriedades úteis.

2
Tarefa
C# SELF, nível 35, lição 2
Bloqueado
Criação e gravação de dados em arquivo
Criação e gravação de dados em arquivo
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION