Java Ler e Escrever Arquivos
Até aqui, tudo o que seus programas sabiam sumia quando eles terminavam. Com arquivos, o programa lê dados que já existem (uma planilha, um log) e grava resultados que continuam lá depois. Nesta aula você usa o pacote moderno java.nio.file para ler a planilha de alunos da Ana, gravar relatórios, criar pastas e lidar com os erros de arquivo mais comuns.
- Representar caminhos com
Path.of, e a diferença entre caminho relativo e absoluto. - Ler um arquivo inteiro (
Files.readString) ou linha por linha (readAllLines,lines). - Gravar (
writeString,write) e acrescentar no fim (APPEND). - Conferir, criar, listar e apagar:
exists,createDirectories,list,delete. - Ler e gravar aos poucos com
BufferedReadereBufferedWriter, dentro de try-with-resources. - O que é a codificação UTF-8 e o erro
MalformedInputException. - As exceções de arquivo:
NoSuchFileException,FileAlreadyExistsException,DirectoryNotEmptyException.
Esta aula usa throws, IOException e try-with-resources. Os programas rodam na pasta pessoal da Ana, /home/ana, onde existem a pasta Documentos e, dentro dela, a planilha alunos.csv e a lista de lembretes notas.txt:
$ cat Documentos/alunos.csv nome,idade,cidade,nota Ana,29,Recife,9.5 Bruno,34,Curitiba,7.0 Carla,22,Salvador,8.5 Diego,41,Manaus,6.0 Elisa,27,Porto Alegre,10.0
A ideia antes do código
Um arquivo é como uma gaveta com etiqueta num armário. O caminho é o endereço da gaveta ("armário do escritório, segunda prateleira, gaveta alunos.csv"). Para usar a gaveta, você precisa de duas coisas: saber o endereço (Path) e alguém que abra, leia e guarde coisas nela (a classe Files, cheia de métodos estáticos prontos).
E, como a gaveta pode não estar lá, estar trancada ou o armário pode estar cheio, quase todos os métodos de Files lançam IOException, uma exceção checked. Nos exemplos curtos, o main declara throws IOException; nos programas de verdade, trate com try/catch.
Caminhos: Path
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class Main {
public static void main(String[] args) throws IOException {
Path arquivo = Path.of("Documentos", "alunos.csv");
System.out.println("Caminho: " + arquivo);
System.out.println("Nome: " + arquivo.getFileName());
System.out.println("Pasta: " + arquivo.getParent());
System.out.println("Absoluto: " + arquivo.toAbsolutePath());
System.out.println("É absoluto? " + arquivo.isAbsolute());
System.out.println("Existe? " + Files.exists(arquivo));
System.out.println("É pasta? " + Files.isDirectory(arquivo));
System.out.println("Tamanho: " + Files.size(arquivo) + " bytes");
System.out.println("Existe fotos.zip? " + Files.exists(Path.of("Documentos/fotos.zip")));
}
}
$ java Main.java Caminho: Documentos/alunos.csv Nome: alunos.csv Pasta: Documentos Absoluto: /home/ana/Documentos/alunos.csv É absoluto? false Existe? true É pasta? false Tamanho: 132 bytes Existe fotos.zip? false
- import java.nio.file.Path; e Files;
- As duas classes da aula ficam em
java.nio.file("new input/output", a entrada e saída "nova", de 2011). AIOExceptionfica emjava.io. - Path.of("Documentos", "alunos.csv")
- Monta o caminho juntando as partes com o separador do sistema (
/no Linux e no macOS,\no Windows).Path.of("Documentos/alunos.csv")também funciona. Java 11+; antes,Paths.get(…). - getFileName(), getParent()
- O último pedaço (o nome) e o caminho da pasta que o contém.
- toAbsolutePath()
- O caminho completo, a partir da raiz
/. - Files.exists, isDirectory, size
- Perguntas ao sistema de arquivos: existe? é pasta? quantos bytes? Criar um
Pathnão cria nem confere nada: é só um endereço.
Relativo × absoluto
Documentos/alunos.csv é um caminho relativo: ele parte da pasta atual, aquela em que o terminal estava quando o programa foi iniciado (a mesma ideia do pwd no terminal). Um caminho absoluto começa na raiz: /home/ana/Documentos/alunos.csv. Veja o mesmo programa rodado de dentro da pasta java:
$ cd java $ java Main.java Caminho: Documentos/alunos.csv Nome: alunos.csv Pasta: Documentos Absoluto: /home/ana/java/Documentos/alunos.csv É absoluto? false Existe? false É pasta? false Exception in thread "main" java.nio.file.NoSuchFileException: Documentos/alunos.csv at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) at java.base/sun.nio.fs.UnixFileAttributeViews$Basic.readAttributes(UnixFileAttributeViews.java:57) at java.base/sun.nio.fs.UnixFileSystemProvider.readAttributes(UnixFileSystemProvider.java:161) at java.base/sun.nio.fs.LinuxFileSystemProvider.readAttributes(LinuxFileSystemProvider.java:99) at java.base/java.nio.file.Files.readAttributes(Files.java:1702) at java.base/java.nio.file.Files.size(Files.java:2242) at Main.main(Main.java:15)
O toAbsolutePath() mostra o que aconteceu: o Java procurou em /home/ana/java/Documentos/alunos.csv, que não existe. O exists respondeu false sem reclamar, mas o size precisa do arquivo e lançou NoSuchFileException ("não existe tal arquivo"). Esse é o erro de arquivo mais comum de todos: o caminho está certo, mas o programa foi iniciado em outra pasta.
Para arquivos da pasta pessoal, monte o caminho a partir dela: Path.of(System.getProperty("user.home"), "Documentos", "alunos.csv"). A propriedade user.home vale /home/ana na máquina da Ana (e C:\Users\ana no Windows). Para saber de onde o programa foi iniciado, Path.of("").toAbsolutePath().
Ler um arquivo
Duas formas, para os dois casos mais comuns: o arquivo inteiro num texto só, ou uma lista com uma linha em cada posição.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
String lembretes = Files.readString(Path.of("Documentos/notas.txt"));
System.out.print(lembretes);
System.out.println("---");
List<String> linhas = Files.readAllLines(Path.of("Documentos/alunos.csv"));
System.out.println("Linhas: " + linhas.size());
System.out.println("Cabeçalho: " + linhas.get(0));
double soma = 0;
for (int i = 1; i < linhas.size(); i++) {
String[] campos = linhas.get(i).split(",");
String nome = campos[0];
double nota = Double.parseDouble(campos[3]);
System.out.println(nome + " tirou " + nota);
soma += nota;
}
System.out.printf("Média da turma: %.2f%n", soma / (linhas.size() - 1));
}
}
$ java Main.java Comprar café Ligar para o João Estudar Bash Fazer backup das fotos --- Linhas: 6 Cabeçalho: nome,idade,cidade,nota Ana tirou 9.5 Bruno tirou 7.0 Carla tirou 8.5 Diego tirou 6.0 Elisa tirou 10.0 Média da turma: 8,20
- Files.readString(path)
- Lê o arquivo inteiro como uma
String, com as quebras de linha dentro. Por isso oprint(sem ln): o texto já termina com uma quebra. Java 11+ - Files.readAllLines(path)
- Lê tudo e devolve uma
List<String>, uma linha por posição, já sem as quebras.size()é o número de linhas eget(0)a primeira (veja ArrayList). - for (int i = 1; …)
- Começa em 1 para pular o cabeçalho.
- split(",")
- Corta a linha nas vírgulas:
campos[0]é o nome,campos[3]a nota (veja Métodos de String). - Double.parseDouble(campos[3])
- A nota está como texto no arquivo; vira número (veja Wrappers). O CSV usa ponto, que é o que o
parseDoubleentende. - printf("%.2f")
- A média, em formato brasileiro:
8,20(veja Formatar Texto).
Os dois métodos carregam o arquivo inteiro na memória. Para arquivos de alguns megabytes, sem problema. Para arquivos enormes (um log de vários gigabytes), leia aos poucos: com Files.lines ou BufferedReader, mais adiante.
Missão: o programa grava uma lista de compras em lista.txt. Complete-o: leia o arquivo de volta com Files.readAllLines e mostre 3 itens: [pão, leite, café] (o tamanho da lista e a própria lista).
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
Path lista = Path.of("lista.txt");
Files.writeString(lista, "pão\nleite\ncafé\n");
// leia o arquivo e mostre quantos itens ele tem
}
}
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
Path lista = Path.of("lista.txt");
Files.writeString(lista, "pão\nleite\ncafé\n");
List<String> itens = Files.readAllLines(lista);
System.out.println(itens.size() + " itens: " + itens);
}
}
Escrever um arquivo
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
Path compras = Path.of("Documentos/compras.txt");
Files.writeString(compras, "pão\nleite\n");
Files.writeString(compras, "café\n", StandardOpenOption.APPEND);
Path aprovados = Path.of("Documentos/aprovados.txt");
List<String> nomes = List.of("Ana", "Carla", "Elisa");
Files.write(aprovados, nomes);
System.out.println("Gravei " + Files.size(compras) + " bytes em " + compras);
System.out.println("Gravei " + nomes.size() + " linhas em " + aprovados);
}
}
$ java Main.java Gravei 17 bytes em Documentos/compras.txt Gravei 3 linhas em Documentos/aprovados.txt $ cat Documentos/compras.txt pão leite café $ cat Documentos/aprovados.txt Ana Carla Elisa $ java Main.java Gravei 17 bytes em Documentos/compras.txt Gravei 3 linhas em Documentos/aprovados.txt $ cat Documentos/compras.txt pão leite café
- Files.writeString(path, texto)
- Grava o texto no arquivo. Se ele não existe, é criado; se existe, é substituído (o conteúdo antigo se perde). Não pula linha sozinho: os
\nsão seus. - StandardOpenOption.APPEND
- "Acrescentar": grava no fim, mantendo o que já existia. Bom para logs e registros.
- Files.write(path, lista)
- Grava uma lista de textos, um por linha, com a quebra de linha no fim de cada um.
List.of(…)cria uma lista pronta (veja Coleções).
Repare no segundo java Main.java: o arquivo de compras continuou com 3 itens, e não 6. O primeiro writeString substituiu tudo, e o APPEND acrescentou o café de novo. E por que 17 bytes, se são 15 letras e quebras? Porque ã e é ocupam 2 bytes cada na codificação UTF-8 (assunto mais abaixo).
writeString e write sem opções começam o arquivo do zero. Se o arquivo for importante, confira antes com Files.exists, grave com outro nome ou use StandardOpenOption.CREATE_NEW, que lança FileAlreadyExistsException em vez de sobrescrever.
Pastas: criar, listar, apagar
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) throws IOException {
Path pasta = Path.of("Documentos/relatorios/2026");
Files.createDirectories(pasta);
Files.writeString(pasta.resolve("outubro.txt"), "Vendas: 1520\n");
Files.writeString(pasta.resolve("novembro.txt"), "Vendas: 1710\n");
try (Stream<Path> itens = Files.list(pasta)) {
for (Path p : itens.sorted().toList()) {
System.out.println(p.getFileName() + " (" + Files.size(p) + " bytes)");
}
}
try (Stream<String> linhas = Files.lines(Path.of("Documentos/acesso.log"))) {
System.out.println("O log tem " + linhas.count() + " linhas");
}
Files.delete(pasta.resolve("novembro.txt"));
System.out.println("Ainda existe novembro.txt? " + Files.exists(pasta.resolve("novembro.txt")));
System.out.println("Apagou? " + Files.deleteIfExists(pasta.resolve("dezembro.txt")));
}
}
$ java Main.java novembro.txt (13 bytes) outubro.txt (13 bytes) O log tem 6 linhas Ainda existe novembro.txt? false Apagou? false $ ls -R Documentos/relatorios Documentos/relatorios: 2026 Documentos/relatorios/2026: outubro.txt
- Files.createDirectories(pasta)
- Cria a pasta e todas as que faltarem no caminho (
relatoriose2026), como omkdir -pdo terminal. Se já existirem, não faz nada. (createDirectory, no singular, cria só uma e reclama se ela já existe.) - pasta.resolve("outubro.txt")
- Um caminho "dentro" de outro:
Documentos/relatorios/2026/outubro.txt. - Files.list(pasta)
- O conteúdo da pasta, como um
Stream<Path>, uma sequência de caminhos que você vai estudar em Streams. Aqui,sorted()ordena por nome etoList()transforma numListcomum. O stream mantém a pasta aberta, por isso fica num try-with-resources. - Files.lines(path)
- As linhas do arquivo como um
Stream<String>, lidas aos poucos (bom para arquivos grandes).count()conta. Também precisa de try-with-resources. - Files.delete(path)
- Apaga (arquivo ou pasta vazia). Se não existir, lança
NoSuchFileException. - Files.deleteIfExists(path)
- Apaga se existir e devolve
true; se não existir, devolvefalsesem exceção.
Atenção: Files.delete apaga de verdade, sem passar pela lixeira.
Aos poucos: BufferedReader e BufferedWriter
Para processar um arquivo linha por linha, sem carregar tudo na memória, e gravar o resultado aos poucos, use um leitor e um escritor "com buffer" (um buffer é uma área de memória intermediária: em vez de ir ao disco a cada letra, o Java lê e grava em blocos). Eles são recursos: precisam ser fechados, e o try-with-resources faz isso. A Ana quer um arquivo só com os aprovados (nota 7 ou mais):
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class Main {
public static void main(String[] args) {
Path entrada = Path.of("Documentos/alunos.csv");
Path saida = Path.of("Documentos/aprovados.csv");
try (BufferedReader leitor = Files.newBufferedReader(entrada);
BufferedWriter escritor = Files.newBufferedWriter(saida)) {
String cabecalho = leitor.readLine();
escritor.write(cabecalho);
escritor.newLine();
String linha;
int aprovados = 0;
while ((linha = leitor.readLine()) != null) {
double nota = Double.parseDouble(linha.split(",")[3]);
if (nota >= 7.0) {
escritor.write(linha);
escritor.newLine();
aprovados++;
}
}
System.out.println(aprovados + " aprovados gravados em " + saida);
} catch (IOException e) {
System.out.println("Erro de arquivo: " + e);
}
}
}
$ java Main.java 4 aprovados gravados em Documentos/aprovados.csv $ cat Documentos/aprovados.csv nome,idade,cidade,nota Ana,29,Recife,9.5 Bruno,34,Curitiba,7.0 Carla,22,Salvador,8.5 Elisa,27,Porto Alegre,10.0
- Files.newBufferedReader(entrada)
- Abre o arquivo para leitura. Fica em
java.io.BufferedReader. - Files.newBufferedWriter(saida)
- Abre (cria ou substitui) o arquivo para escrita.
- leitor.readLine()
- Lê a próxima linha, sem a quebra. No fim do arquivo, devolve
null. - while ((linha = leitor.readLine()) != null)
- A forma clássica: lê uma linha, guarda em
linhae, se não fornull, executa o corpo. Os parênteses em volta da atribuição são obrigatórios. - escritor.write(texto); escritor.newLine();
- Grava o texto e uma quebra de linha.
- try ( … ; … )
- Os dois recursos são fechados no fim, na ordem inversa. Fechar o escritor é essencial: é no
close()que o que sobrou no buffer vai para o disco. Sem ele, o fim do arquivo pode se perder.
Codificação: UTF-8
Um arquivo de texto é uma sequência de bytes. A codificação (charset, encoding) é a tabela que diz qual byte vira qual letra. Para as letras sem acento, quase todas as tabelas concordam. Para ã, é, ç, não. Hoje o padrão do mundo é o UTF-8, em que cada letra acentuada ocupa 2 bytes (por isso o compras.txt tinha 17 bytes).
Os métodos de Files usam UTF-8 quando você não diz nada. E desde o Java 18, UTF-8 é o padrão de todo o Java, em qualquer sistema Java 18+. Arquivos antigos, de programas do Windows, às vezes vêm em ISO-8859-1 (também chamado Latin-1), onde ã é um byte só. A Ana recebeu um assim:
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
public class Main {
public static void main(String[] args) throws IOException {
System.out.println("Codificação padrão: " + Charset.defaultCharset());
Path antigo = Path.of("Documentos/clientes-antigo.txt");
System.out.println(Files.readString(antigo, StandardCharsets.ISO_8859_1));
System.out.println(Files.readString(antigo));
}
}
$ printf 'Jo\343o;S\343o Paulo\n' > Documentos/clientes-antigo.txt $ file Documentos/clientes-antigo.txt Documentos/clientes-antigo.txt: ISO-8859 text $ java Main.java Codificação padrão: UTF-8 João;São Paulo Exception in thread "main" java.nio.charset.MalformedInputException: Input length = 3 at java.base/java.lang.String.throwMalformed(String.java:1281) at java.base/java.lang.String.decodeUTF8_UTF16(String.java:1168) at java.base/java.lang.String.newStringUTF8NoRepl(String.java:768) at java.base/java.lang.String.newStringNoRepl1(String.java:798) at java.base/java.lang.String.newStringNoRepl(String.java:781) at java.base/java.lang.System$1.uncheckedNewStringNoRepl(System.java:2129) at java.base/java.nio.file.Files.readString(Files.java:3046) at java.base/java.nio.file.Files.readString(Files.java:3006) at Main.main(Main.java:12)
O printf do terminal criou o arquivo com o byte \343 (o ã do Latin-1), e o comando file confirma: ISO-8859 text. Lendo com StandardCharsets.ISO_8859_1, o texto saiu certo. Lendo com o padrão (UTF-8), aqueles bytes não formam nenhuma letra válida em UTF-8, e o readString lança MalformedInputException ("entrada malformada", uma filha de IOException). Todos os métodos de leitura e escrita de Files aceitam o charset como argumento extra.
Se aparecer MalformedInputException, ou textos como João (UTF-8 lido como Latin-1) ou Jo�o, o arquivo e o programa estão usando tabelas diferentes. Descubra a codificação do arquivo (o comando file ajuda) e passe o StandardCharsets certo. Ao gravar, prefira sempre UTF-8.
Qual método usar
| Você quer… | Use |
|---|---|
| Ler um arquivo pequeno inteiro | Files.readString(path) |
| Ler as linhas de um arquivo pequeno | Files.readAllLines(path) |
| Ler um arquivo grande, linha a linha | Files.newBufferedReader ou Files.lines (com try-with-resources) |
| Gravar um texto | Files.writeString(path, texto) |
| Gravar uma lista, uma por linha | Files.write(path, lista) |
| Acrescentar no fim | …, StandardOpenOption.APPEND |
| Gravar muitas linhas aos poucos | Files.newBufferedWriter (com try-with-resources) |
Ler com Scanner | new Scanner(path) (veja finally e try-with-resources) |
Código antigo com File, FileReader, FileWriter | Funciona, mas prefira Path e Files: mensagens de erro melhores e UTF-8 por padrão |
Quando dá errado
Todas estas exceções são filhas de IOException, e todas aparecem com o caminho na mensagem.
NoSuchFileException: o arquivo não existe (ali)
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class Main {
public static void main(String[] args) throws IOException {
String texto = Files.readString(Path.of("Documentos/nota.txt"));
System.out.println(texto);
}
}
$ java Main.java Exception in thread "main" java.nio.file.NoSuchFileException: Documentos/nota.txt at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) at java.base/sun.nio.fs.UnixFileSystemProvider.newFileChannel(UnixFileSystemProvider.java:213) at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:244) at java.base/java.nio.file.Files.newByteChannel(Files.java:357) at java.base/java.nio.file.Files.newByteChannel(Files.java:399) at java.base/java.nio.file.Files.readAllBytes(Files.java:2973) at java.base/java.nio.file.Files.readString(Files.java:3043) at java.base/java.nio.file.Files.readString(Files.java:3006) at Main.main(Main.java:7)
O que aconteceu: o arquivo se chama notas.txt; faltou o s. A mensagem mostra exatamente o caminho que o Java tentou.
Como resolver: confira o nome (maiúsculas e minúsculas contam no Linux), a extensão e a pasta atual (Path.of("").toAbsolutePath()). Num programa para usuários, trate com catch (NoSuchFileException e) e mostre uma mensagem amigável.
DirectoryNotEmptyException e FileAlreadyExistsException
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class Main {
public static void main(String[] args) {
Path[] pastas = {Path.of("Documentos/relatorios"), Path.of("Documentos/relatorios/2026")};
for (Path p : pastas) {
try {
Files.delete(p);
System.out.println("Apaguei " + p);
} catch (IOException e) {
System.out.println("Não apaguei: " + e);
}
}
try {
Files.createDirectory(Path.of("Documentos"));
} catch (IOException e) {
System.out.println("Não criei: " + e);
}
}
}
$ java Main.java Não apaguei: java.nio.file.DirectoryNotEmptyException: Documentos/relatorios Não apaguei: java.nio.file.DirectoryNotEmptyException: Documentos/relatorios/2026 Não criei: java.nio.file.FileAlreadyExistsException: Documentos
O que aconteceu: Files.delete só apaga pastas vazias (relatorios tem 2026, que tem outubro.txt). E createDirectory, no singular, recusa uma pasta que já existe.
Como resolver: apague primeiro o conteúdo (dos arquivos para as pastas). Para criar sem se preocupar, use createDirectories, no plural.
O que aconteceu: quase todo método de Files declara throws IOException, uma exceção checked.
Como resolver: acrescente throws IOException no seu método (e o import java.io.IOException;) ou use try/catch. Veja Checked × Unchecked.
O que aconteceu: um BufferedWriter que não foi fechado. O que estava no buffer nunca chegou ao disco.
Como resolver: abra o escritor num try-with-resources, para o close() acontecer sempre.
Referência
| Código | O que faz |
|---|---|
Path.of("pasta", "arquivo.txt") | Monta um caminho |
p.getFileName(), getParent(), toAbsolutePath(), resolve("x") | Nome, pasta, caminho completo, caminho dentro |
Files.exists(p), isDirectory(p), size(p) | Existe? É pasta? Quantos bytes? |
Files.readString(p) | Arquivo inteiro → String |
Files.readAllLines(p) | Arquivo → List<String> |
Files.lines(p) | Linhas aos poucos (Stream; try-with-resources) |
Files.writeString(p, texto) | Grava (cria ou substitui) |
Files.write(p, lista) | Grava uma linha por item |
StandardOpenOption.APPEND / CREATE_NEW | Acrescentar / só criar se não existir |
Files.createDirectories(p) | Cria a pasta e as que faltarem |
Files.list(p) | Conteúdo de uma pasta (Stream<Path>) |
Files.delete(p) / deleteIfExists(p) | Apaga (sem lixeira) |
Files.copy(a, b) / Files.move(a, b) | Copia / move ou renomeia (StandardCopyOption.REPLACE_EXISTING para substituir) |
Files.newBufferedReader(p) / newBufferedWriter(p) | Leitor e escritor aos poucos (readLine, write, newLine) |
Files.readString(p, StandardCharsets.ISO_8859_1) | Ler com outra codificação |
System.getProperty("user.home") | A pasta pessoal |
Exercícios
1. O arquivo inteiro
Complete para ler o arquivo inteiro como texto:
2. Acrescentar no fim
Complete para gravar no fim do arquivo, sem apagar o que existe:
3. Fim do arquivo
O que o readLine() de um BufferedReader devolve quando não há mais linhas?
4. O programa usa Path.of("Documentos/alunos.csv") e funciona quando rodado em /home/ana. Rodado em /home/ana/java, lança NoSuchFileException. Por quê?
5. O arquivo log.txt tem 10 linhas. O que acontece com Files.writeString(Path.of("log.txt"), "oi\n")?
6. Por que usar try-with-resources com Files.newBufferedWriter?
Missão final: grave os registros no arquivo notas.csv com Files.write, leia o arquivo de volta com Files.readAllLines, separe cada linha na vírgula e calcule a média das notas. Mostre com printf("Média: %.2f%n", …): no locale brasileiro, Média: 8,33.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
Path arquivo = Path.of("notas.csv");
List<String> registros = List.of("Ana,9.5", "Bruno,7.0", "Carla,8.5");
// 1. grave os registros no arquivo
// 2. leia as linhas de volta
// 3. some as notas e mostre a média
}
}
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
Path arquivo = Path.of("notas.csv");
List<String> registros = List.of("Ana,9.5", "Bruno,7.0", "Carla,8.5");
Files.write(arquivo, registros);
List<String> linhas = Files.readAllLines(arquivo);
double soma = 0;
for (String linha : linhas) {
soma += Double.parseDouble(linha.split(",")[1]);
}
System.out.printf("Média: %.2f%n", soma / linhas.size());
}
}
Resumo
Path.of(…)é o endereço;Filesfaz o trabalho. Quase tudo lançaIOException(checked).- Caminhos relativos partem da pasta onde o programa foi iniciado;
toAbsolutePath()mostra onde o Java está procurando. Para a pasta pessoal,System.getProperty("user.home"). - Ler:
readString(tudo),readAllLines(lista),linesouBufferedReader(aos poucos). - Gravar:
writeStringewritesubstituem o arquivo;APPENDacrescenta;BufferedWritergrava aos poucos e precisa ser fechado. - Pastas:
createDirectories,list,delete(só vazias),deleteIfExists. - O padrão é UTF-8; arquivos em outra codificação lançam
MalformedInputException: passe oStandardCharsetscerto. - Erros comuns:
NoSuchFileException(nome ou pasta atual errados),FileAlreadyExistsException,DirectoryNotEmptyException.