1. Leitura do arquivo inteiro
Leitura de todos os bytes
Às vezes é preciso extrair todo o conteúdo de um arquivo de uma só vez — como está, sem analisar, seja uma imagem, um arquivo compactado ou algum formato binário. Para isso, o Java tem o método Files.readAllBytes(path). Ele retorna um array de bytes (byte[]), ou seja, dados brutos do arquivo, que você pode usar como quiser.
import java.nio.file.*;
public class ReadBytesExample {
public static void main(String[] args) throws Exception {
Path path = Paths.get("example.txt");
byte[] allBytes = Files.readAllBytes(path);
System.out.println("Tamanho do arquivo em bytes: " + allBytes.length);
}
}
Observação: Se o arquivo for grande (gigabytes), essa abordagem pode causar problemas de memória — afinal, todo o conteúdo do arquivo é carregado de uma vez na RAM.
Leitura de todas as linhas
Para arquivos de texto há um jeito mais amigável: Files.readAllLines(path). Ele retorna uma lista de linhas (List<String>), em que cada elemento é uma linha do arquivo (os separadores de linha são tratados automaticamente).
import java.nio.file.*;
import java.util.List;
public class ReadLinesExample {
public static void main(String[] args) throws Exception {
Path path = Paths.get("example.txt");
List<String> lines = Files.readAllLines(path);
for (String line : lines) {
System.out.println(line);
}
}
}
Importante: Por padrão é usada a codificação do sistema. Se quiser especificar a codificação explicitamente (por exemplo, UTF-8), use a versão sobrecarregada do método:
List<String> lines = Files.readAllLines(path, java.nio.charset.StandardCharsets.UTF_8);
Exemplo: ler um arquivo e imprimir na tela
Vamos adicionar isso ao nosso miniaplicativo (por exemplo, um “bloco de notas” ou uma “lista de tarefas”):
import java.nio.file.*;
import java.util.List;
public class TodoReader {
public static void main(String[] args) throws Exception {
Path todoPath = Paths.get("todo.txt");
if (Files.exists(todoPath)) {
List<String> tasks = Files.readAllLines(todoPath);
System.out.println("Suas tarefas para hoje:");
for (String task : tasks) {
System.out.println("- " + task);
}
} else {
System.out.println("Arquivo todo.txt não encontrado. Crie uma lista de tarefas!");
}
}
}
2. Gravação em arquivo
Gravação de array de bytes
Se você tem um array de bytes (por exemplo, resultado de serialização, imagem, áudio), use Files.write(path, bytes). Esse método cria o arquivo se ele não existir ou sobrescreve o existente.
import java.nio.file.*;
public class WriteBytesExample {
public static void main(String[] args) throws Exception {
Path path = Paths.get("output.bin");
byte[] data = {1, 2, 3, 4, 5};
Files.write(path, data);
System.out.println("Bytes gravados no arquivo output.bin");
}
}
Gravação de lista de strings
Para arquivos de texto é mais conveniente usar uma lista de strings — cada linha será gravada separadamente, com quebra de linha.
import java.nio.file.*;
import java.util.Arrays;
import java.util.List;
public class WriteLinesExample {
public static void main(String[] args) throws Exception {
Path path = Paths.get("todo.txt");
List<String> tasks = Arrays.asList(
"Comprar leite",
"Ligar para a avó",
"Fazer a lição de casa de Java"
);
Files.write(path, tasks);
System.out.println("Lista de tarefas gravada em todo.txt");
}
}
Atenção: Por padrão o arquivo será sobrescrito! Se ele já existia, as tarefas antigas desaparecerão. (Como não perder o antigo — contaremos um pouco mais adiante.)
Gravar uma string em arquivo
Se quiser gravar apenas uma linha, crie uma lista com uma única string ou use Files.write(path, string.getBytes()):
import java.nio.file.*;
public class WriteStringExample {
public static void main(String[] args) throws Exception {
Path path = Paths.get("hello.txt");
String message = "Olá, Java!";
Files.write(path, message.getBytes());
System.out.println("Linha gravada em hello.txt");
}
}
Especificando a codificação explicitamente
Para evitar caracteres estranhos ao trabalhar com texto em russo (e não só), sempre especifique a codificação:
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.List;
public class WriteLinesUtf8Example {
public static void main(String[] args) throws Exception {
Path path = Paths.get("hello.txt");
List<String> lines = List.of("Olá, mundo!", "Isto é Java.");
Files.write(path, lines, StandardCharsets.UTF_8);
}
}
3. Tratamento de erros
Ao trabalhar com arquivos, o Java pode lançar a exceção IOException. É um sinal geral de que “algo deu errado” no nível de entrada e saída. As causas podem ser muitas: o arquivo simplesmente não existe, faltam permissões, o disco está cheio ou ocupado, ou às vezes até o pendrive foi desconectado no pior momento.
Por isso, os métodos de leitura e escrita de arquivos exigem que estejamos prontos para tratar tais situações. Isso é feito com try-catch:
import java.nio.file.*;
import java.util.List;
import java.io.IOException;
public class SafeReadExample {
public static void main(String[] args) {
Path path = Paths.get("todo.txt");
try {
List<String> lines = Files.readAllLines(path);
System.out.println("Conteúdo do arquivo:");
for (String line : lines) {
System.out.println(line);
}
} catch (IOException ex) {
System.out.println("Erro ao ler o arquivo: " + ex.getMessage());
}
}
}
Por que tudo isso?
try-catch transforma um possível colapso do programa em uma situação controlada. Se o arquivo não existir — informamos o usuário calmamente. Se o sistema não der acesso — apontamos o problema. E se o disco “sumir” no meio da operação, o programa não vai cair com um stack trace assustador; ao menos avisará com uma mensagem normal. Em outras palavras: IOException não é um inimigo, é apenas a forma de o Java nos dizer: “ei, algo lá fora deu errado; pense no que fazer a seguir”.
4. Exemplos práticos
Ler um arquivo e exibir o conteúdo
import java.nio.file.*;
import java.util.List;
import java.io.IOException;
public class PrintFileExample {
public static void main(String[] args) {
Path path = Paths.get("notes.txt");
try {
if (!Files.exists(path)) {
System.out.println("Arquivo notes.txt não encontrado.");
return;
}
List<String> lines = Files.readAllLines(path, java.nio.charset.StandardCharsets.UTF_8);
System.out.println("Conteúdo do arquivo notes.txt:");
for (String line : lines) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("Erro ao ler o arquivo: " + e.getMessage());
}
}
}
Gravar uma string em um novo arquivo
import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.io.IOException;
public class WriteFileExample {
public static void main(String[] args) {
Path path = Paths.get("greeting.txt");
String content = "Bem-vindo ao mundo do Java IO!";
try {
Files.write(path, content.getBytes(StandardCharsets.UTF_8));
System.out.println("Linha gravada no arquivo greeting.txt");
} catch (IOException e) {
System.out.println("Erro ao gravar o arquivo: " + e.getMessage());
}
}
}
Gravar uma lista de strings em arquivo
import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.io.IOException;
public class WriteListExample {
public static void main(String[] args) {
Path path = Paths.get("shopping.txt");
List<String> items = List.of("Pão", "Leite", "Queijo");
try {
Files.write(path, items, StandardCharsets.UTF_8);
System.out.println("Lista de compras gravada em shopping.txt");
} catch (IOException e) {
System.out.println("Erro ao gravar o arquivo: " + e.getMessage());
}
}
}
5. Resumo sobre streams
Os métodos Files.readAllBytes, Files.readAllLines, Files.write são “tudo de uma vez”: ou todo o arquivo vai para a memória, ou todo o conteúdo é gravado de uma vez no disco. Para arquivos pequenos isso é prático, mas para arquivos grandes nem tanto (você pode ter OutOfMemoryError ou simplesmente “travar” ao ler logs de gigabytes).
Para trabalhar com arquivos grandes ou leitura linha a linha usam-se streams:
- Para texto: BufferedReader, BufferedWriter
- Para bytes: InputStream, OutputStream
Falaremos mais sobre streams nas próximas aulas, mas aqui vai um pequeno teaser:
import java.nio.file.*;
import java.io.*;
public class BufferedReaderExample {
public static void main(String[] args) {
Path path = Paths.get("bigfile.txt");
try (BufferedReader reader = Files.newBufferedReader(path)) {
String line;
while ((line = reader.readLine()) != null) {
// Processando a linha
System.out.println(line);
}
} catch (IOException e) {
System.out.println("Erro ao ler o arquivo: " + e.getMessage());
}
}
}
6. Detalhes úteis
- Sobrescrita de arquivo: Todos os métodos Files.write sobrescrevem o arquivo por padrão. Se precisar adicionar no final, use opções adicionais (falaremos sobre isso na próxima aula).
- Codificação: Sempre especifique a codificação explicitamente ao trabalhar com texto não ASCII. Isso evita “caracteres estranhos” na saída. Uma boa escolha é StandardCharsets.UTF_8.
- Caminhos: Use Paths.get(...) para garantir multiplataforma. Nunca faça hardcode das barras (/ ou \) manualmente.
- Nomes de arquivos: Não use caracteres proibidos no nome do arquivo (?, *, :, <, >, | etc.), especialmente se seu código precisar rodar no Windows.
7. Erros comuns ao ler e escrever arquivos
Erro nº 1: IOException não é tratada. Com frequência iniciantes escrevem Files.readAllLines(path) sem try-catch, e no primeiro problema (arquivo não encontrado, falta de permissão, disco corrompido) o programa cai. Sempre trate as exceções!
Erro nº 2: trabalhar com arquivos grandes usando readAllBytes/readAllLines. Se o arquivo tem centenas de megabytes ou gigabytes, tentar carregá-lo inteiro pode “matar” seu programa. Para esses casos use streams (BufferedReader).
Erro nº 3: codificação não especificada na gravação/leitura de texto. Se você não especificar a codificação, o resultado pode variar entre computadores e sistemas operacionais. O problema aparece com frequência com alfabetos como o cirílico. Use StandardCharsets.UTF_8 ou a codificação necessária explicitamente.
Erro nº 4: achar que File/Path é o próprio arquivo. A classe File ou Path é apenas um “atalho” para o arquivo, não o arquivo em si. Ao criar o objeto você não cria o arquivo no disco. Para criar o arquivo — use os métodos Files.createFile, Files.write e assim por diante.
Erro nº 5: não fechar o stream (se você usa streams). Se você usa streams manualmente (por exemplo, BufferedReader), feche-os sempre (de preferência com try-with-resources). Caso contrário, o arquivo pode ficar “bloqueado” e indisponível para outros programas.
GO TO FULL VERSION