💻 Exemplos: Capítulo 12: Persistência e Manipulação de Arquivos: I/O Tradicional, Java NIO.2, Buffers e Streams
Especialização em Sistemas com Java 21 LTS • Capítulo 12
🎯 Visão Geral dos Exemplos Práticos
Neste laboratório prático, implementaremos exemplos corporativos completos explorando:
- Pipeline de Ingestão de Dados com NIO.2: criação estruturada de diretórios, escrita bufferizada em UTF-8 e leitura de linhas com streams preguiçosos.
- Varredura Recursiva com
Files.walk: catalogação e auditoria forense de arquivos de log por extensão e tamanho em disco. - Operações Atômicas de Sistema de Arquivos: movimentação atômica de arquivos de lote (
ATOMIC_MOVE) para garantir tolerância a falhas.
💻 Exemplo 01 — Pipeline de Processamento e Transição de Lotes com Java NIO.2
package com.empresa.arquivos;
import java.io.BufferedWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.time.LocalDate;
import java.util.stream.Stream;
/**
* Pipeline corporativo de ingestão, cálculo e arquivamento de remessas com NIO.2.
*/
public class PipelineIngestaoLotes {
public record RegistroFinanceiro(long id, String sacado, BigDecimal valor, boolean liquidado) {}
public static void main(String[] args) {
System.out.println("================================================================================");
System.out.println(" PIPELINE DE PROCESSAMENTO DE ARQUIVOS COM JAVA NIO.2 (JAVA 21) ");
System.out.println("================================================================================");
try {
// Criação de diretório temporário isolado para a execução
Path dirTrabalho = Files.createTempDirectory("pipeline_lotes_");
Path dirEntrada = dirTrabalho.resolve("inbound");
Path dirProcessados = dirTrabalho.resolve("archive");
Files.createDirectories(dirEntrada);
Files.createDirectories(dirProcessados);
Path arquivoRemessa = dirEntrada.resolve("remessa_" + LocalDate.now() + ".csv");
// 1. Geração do Arquivo de Dados com BufferedWriter
try (BufferedWriter writer = Files.newBufferedWriter(arquivoRemessa, StandardCharsets.UTF_8,
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
writer.write("ID;SACADO;VALOR;STATUS\n");
writer.write("1001;Hospital Santa Cruz;54200.00;LIQUIDADO\n");
writer.write("1002;Universidade Federal;18900.50;PENDENTE\n");
writer.write("1003;Rede Varejo S/A;89450.75;LIQUIDADO\n");
writer.write("1004;Distribuidora Alimentos;12300.00;LIQUIDADO\n");
}
System.out.printf("📁 [1/4] Remessa gerada no diretório: %s%n", arquivoRemessa.toAbsolutePath());
System.out.printf(" Tamanho do arquivo gerado: %d bytes%n%n", Files.size(arquivoRemessa));
// 2. Leitura com Stream lazy (Files.lines) e Processamento
System.out.println("🔍 [2/4] Processando registros da remessa...");
BigDecimal totalLiquidado = BigDecimal.ZERO;
int totalRegistros = 0;
try (Stream<String> linhas = Files.lines(arquivoRemessa, StandardCharsets.UTF_8)) {
for (String linha : (Iterable<String>) linhas.skip(1)::iterator) {
if (linha.isBlank()) continue;
String[] tokens = linha.split(";");
long id = Long.parseLong(tokens[0]);
String sacado = tokens[1];
BigDecimal valor = new BigDecimal(tokens[2]);
boolean liquidado = "LIQUIDADO".equalsIgnoreCase(tokens[3]);
if (liquidado) {
totalLiquidado = totalLiquidado.add(valor);
System.out.printf(" ✅ Remessa #%d - %-25s | R$ %10.2f [PROCESSADA]%n", id, sacado, valor);
} else {
System.out.printf(" ⏳ Remessa #%d - %-25s | R$ %10.2f [AGUARDANDO]%n", id, sacado, valor);
}
totalRegistros++;
}
}
System.out.println("--------------------------------------------------------------------------------");
System.out.printf("Total de Títulos Apurados: %d registros%n", totalRegistros);
System.out.printf("Volume Total Liquidado : R$ %,10.2f%n", totalLiquidado);
// 3. Movimentação Atômica para a pasta de arquivos processados
Path destinoFinal = dirProcessados.resolve(arquivoRemessa.getFileName());
Files.move(arquivoRemessa, destinoFinal, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
System.out.printf("%n🚚 [3/4] Arquivo transferido atomicamente para: %s%n", destinoFinal);
// 4. Verificação de integridade pós-movimentação
boolean origemExiste = Files.exists(arquivoRemessa);
boolean destinoExiste = Files.exists(destinoFinal);
System.out.printf("🔒 [4/4] Integridade: Origem excluída? %b | Destino ativo? %b%n", !origemExiste, destinoExiste);
// Limpeza final do diretório temporário
Files.deleteIfExists(destinoFinal);
Files.deleteIfExists(dirEntrada);
Files.deleteIfExists(dirProcessados);
Files.deleteIfExists(dirTrabalho);
} catch (IOException e) {
System.err.printf("🚨 Erro de I/O no pipeline: %s%n", e.getMessage());
}
System.out.println("================================================================================");
}
}
💻 Exemplo 02 — Varredura e Auditoria Recursiva de Pastas com Files.walk
package com.empresa.arquivos;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;
/**
* Auditoria de armazenamento em disco inspecionando árvores de diretórios.
*/
public class AuditorArmazenamentoDisco {
public static void main(String[] args) {
System.out.println("================================================================================");
System.out.println(" AUDITORIA FORENSE DE DIRETÓRIOS COM FILES.WALK ");
System.out.println("================================================================================");
Path raizAuditoria = Path.of(System.getProperty("user.dir"));
System.out.printf("Inspecionando diretório de trabalho: [%s]%n%n", raizAuditoria.toAbsolutePath());
try (Stream<Path> caminhos = Files.walk(raizAuditoria, 3)) {
caminhos.filter(p -> Files.isRegularFile(p) && p.toString().endsWith(".md"))
.limit(10)
.forEach(arquivo -> {
try {
long bytes = Files.size(arquivo);
System.out.printf("📄 %-45s | %8d bytes%n",
arquivo.getFileName(), bytes);
} catch (IOException ignored) {}
});
} catch (IOException e) {
System.err.println("Falha na varredura: " + e.getMessage());
}
System.out.println("================================================================================");
}
}
📋 Resultado Esperado no Console
================================================================================
PIPELINE DE PROCESSAMENTO DE ARQUIVOS COM JAVA NIO.2 (JAVA 21)
================================================================================
📁 [1/4] Remessa gerada no diretório: C:\Users\AppData\Local\Temp\pipeline_lotes_...\inbound\remessa_2026-09-28.csv
Tamanho do arquivo gerado: 174 bytes
🔍 [2/4] Processando registros da remessa...
✅ Remessa #1001 - Hospital Santa Cruz | R$ 54200.00 [PROCESSADA]
⏳ Remessa #1002 - Universidade Federal | R$ 18900.50 [AGUARDANDO]
✅ Remessa #1003 - Rede Varejo S/A | R$ 89450.75 [PROCESSADA]
✅ Remessa #1004 - Distribuidora Alimentos | R$ 12300.00 [PROCESSADA]
--------------------------------------------------------------------------------
Total de Títulos Apurados: 4 registros
Volume Total Liquidado : R$ 155.950,75
🚚 [3/4] Arquivo transferido atomicamente para: C:\Users\AppData\Local\Temp\pipeline_lotes_...\archive\remessa_2026-09-28.csv
🔒 [4/4] Integridade: Origem excluída? true | Destino ativo? true
================================================================================