Por que trabalhar com arquivos em Java não é assustador?
\n\nTodo desenvolvedor, mesmo que escreva apenas backend em Java, mais cedo ou mais tarde se depara com a necessidade de salvar dados, ler configurações ou processar logs. Trabalhar com arquivos e o sistema de arquivos em Java é uma habilidade básica que transforma aplicações de console "de brinquedo" em utilitários reais. E sim, em 2024, temos não apenas o bom e velho File, mas também o poderoso java.nio.file.
Neste artigo, abordaremos tudo: desde abrir um bloco de notas até manipular permissões de acesso. Vamos lá!
\n\n1. Abordagem clássica: java.io.File
\n\nVamos começar com o avô. A classe File surgiu no Java 1.0 e ainda é usada. Mas sejamos honestos: ela é mais sobre metadados do que sobre conteúdo. Com ela, é possível verificar se um arquivo existe, criar uma pasta, obter uma lista de arquivos.
import java.io.File;\n\npublic class FileExample {\n public static void main(String[] args) {\n File file = new File("/home/user/docs/notes.txt");\n \n System.out.println("Arquivo existe: " + file.exists());\n System.out.println("Caminho absoluto: " + file.getAbsolutePath());\n System.out.println("Tamanho: " + file.length() + " bytes");\n \n // Criando um diretório\n File dir = new File("/home/user/new_folder");\n if (dir.mkdir()) {\n System.out.println("Pasta criada");\n }\n }\n}\n\nDesvantagem: File não consegue ler arquivos grandes adequadamente — para isso, são necessários fluxos. E ele não suporta links simbólicos (soft links) nativamente. Foi por isso que a Sun (e depois a Oracle) lançaram o NIO.
2. Leitura de arquivos: de InputStream a BufferedReader
\n\nA leitura é a operação mais comum. Se o arquivo for de texto, use BufferedReader — ele armazena dados em buffer e funciona rapidamente.
import java.io.BufferedReader;\nimport java.io.FileReader;\nimport java.io.IOException;\n\npublic class ReadFile {\n public static void main(String[] args) {\n try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {\n String line;\n while ((line = br.readLine()) != null) {\n System.out.println(line);\n }\n } catch (IOException e) {\n System.err.println("Erro de leitura: " + e.getMessage());\n }\n }\n}\n\nPara arquivos binários (imagens, arquivos compactados), use FileInputStream:
import java.io.FileInputStream;\nimport java.io.IOException;\n\npublic class ReadBinary {\n public static void main(String[] args) {\n try (FileInputStream fis = new FileInputStream("image.png")) {\n byte[] buffer = new byte[1024];\n int bytesRead;\n while ((bytesRead = fis.read(buffer)) != -1) {\n // processa o trecho buffer[0..bytesRead]\n }\n } catch (IOException e) {\n e.printStackTrace();\n }\n }\n}\n\nImportante: sempre use try-with-resources — isso garante o fechamento do fluxo, mesmo se uma exceção for lançada.
3. Escrita em arquivo: BufferedWriter e FileOutputStream
\n\nA escrita é quase simétrica à leitura. Para texto — BufferedWriter, para dados binários — FileOutputStream.
import java.io.BufferedWriter;\nimport java.io.FileWriter;\nimport java.io.IOException;\n\npublic class WriteFile {\n public static void main(String[] args) {\n try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {\n bw.write("Olá, mundo!");\n bw.newLine();\n bw.write("Java é poderoso.");\n } catch (IOException e) {\n e.printStackTrace();\n }\n }\n}\n\nSe precisar adicionar ao final do arquivo, em vez de sobrescrevê-lo