1. Revisão: File vs Path vs Files
O bom e velho File
Pois é... há bastante código legado em projetos Java. Então vamos relembrar o veterano da linguagem Java, a classe File. Ela apareceu já na primeira versão e permite trabalhar com arquivos e pastas: verificar se um arquivo existe, obter seu nome, tamanho, data de modificação, além de criar e excluir arquivos e pastas. Como já sabemos, ela tem várias limitações: parte dos métodos é pouco intuitiva, nem todas as operações são portáveis entre plataformas, e alguns métodos retornam não exceções, mas simplesmente false (o que nem sempre é conveniente para depuração).
import java.io.File;
File file = new File("example.txt");
System.out.println("O arquivo existe? " + file.exists());
System.out.println("É um arquivo? " + file.isFile());
System.out.println("É uma pasta? " + file.isDirectory());
Path e Files: uma visão moderna (Java 7+)
Com o lançamento do Java 7 surgiu o pacote java.nio.file, que oferece ferramentas mais poderosas e flexíveis. Dois protagonistas principais:
- Path — uma interface que descreve o caminho para um arquivo ou pasta. Dá para dizer que é “uma ‘string inteligente’”: sabe decompor, juntar, analisar e comparar caminhos.
- Files — uma classe utilitária com um monte de métodos estáticos para trabalhar com arquivos e diretórios: criar, excluir, copiar, ler, escrever e obter informações.
import java.nio.file.Path;
import java.nio.file.Paths;
Path path = Paths.get("example.txt");
System.out.println("Caminho: " + path);
Curiosidade: a classe Path — não é apenas uma string! Ela conhece os separadores de diretórios, entende caminhos relativos e absolutos e funciona igualmente bem no Windows e no Linux.
Tabela comparativa: File vs Path/Files
| Critério | File (API antigo) | Path + Files (API moderno) |
|---|---|---|
| Sintaxe | Estilo OO | Combinação de Path + métodos estáticos de Files |
| Portabilidade entre plataformas | Parcial | Excelente, leva o SO em conta |
| Exceções | Nem sempre | Quase sempre |
| Novos recursos | Não | Sim (atributos, permissões, links etc.) |
| Recomendado | Preferencialmente não | Sim |
2. Obtendo informações sobre arquivo/diretório
Vamos ver como descobrir o essencial sobre um arquivo ou pasta: se o objeto existe, seu tipo (arquivo ou diretório), tamanho, nome, caminho e o diretório pai.
Verificando a existência
Com File
File file = new File("example.txt");
if (file.exists()) {
System.out.println("O arquivo existe!");
} else {
System.out.println("Arquivo não encontrado.");
}
Com Path e Files
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
Path path = Paths.get("example.txt");
if (Files.exists(path)) {
System.out.println("O arquivo existe!");
} else {
System.out.println("Arquivo não encontrado.");
}
Dica: Para novos projetos, sempre use Path e Files. É mais seguro, conveniente e multiplataforma.
Verificando o tipo: arquivo ou diretório
File
if (file.isFile()) {
System.out.println("É um arquivo.");
} else if (file.isDirectory()) {
System.out.println("É uma pasta.");
}
Path + Files
if (Files.isRegularFile(path)) {
System.out.println("É um arquivo.");
} else if (Files.isDirectory(path)) {
System.out.println("É uma pasta.");
}
Obtendo o tamanho do arquivo
File
long size = file.length();
System.out.println("Tamanho do arquivo: " + size + " bytes");
Path + Files
try {
long size = Files.size(path);
System.out.println("Tamanho do arquivo: " + size + " bytes");
} catch (IOException e) {
System.out.println("Erro ao obter o tamanho do arquivo: " + e.getMessage());
}
Atenção: Para uma pasta, o método length() sempre retornará 0, e Files.size(path) lançará IOException. O tamanho de uma pasta é a soma dos tamanhos de todos os arquivos dentro dela (mais detalhes nas próximas aulas).
Obtendo caminho absoluto e relativo
File
System.out.println("Caminho relativo: " + file.getPath());
System.out.println("Caminho absoluto: " + file.getAbsolutePath());
Path
System.out.println("Caminho relativo: " + path);
System.out.println("Caminho absoluto: " + path.toAbsolutePath());
Obtendo o nome do arquivo e o diretório pai
File
System.out.println("Nome do arquivo: " + file.getName());
System.out.println("Pasta pai: " + file.getParent());
Path
System.out.println("Nome do arquivo: " + path.getFileName());
System.out.println("Pasta pai: " + path.getParent());
Dica: Path trabalha não apenas com arquivos, mas também com pastas; com caminhos relativos e absolutos; e ainda facilita decompor o caminho em partes.
3. Obtendo atributos do arquivo
Às vezes queremos saber não só o tamanho e o nome, mas também algo mais interessante: data de criação, data da última modificação e permissões de acesso.
Data de criação e última modificação
File (limitado)
long lastModified = file.lastModified();
System.out.println("Data da última modificação: " + new java.util.Date(lastModified));
Limitação: Não é possível obter a data de criação com File!
Path + Files
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
try {
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
FileTime creationTime = attrs.creationTime();
FileTime lastModifiedTime = attrs.lastModifiedTime();
System.out.println("Data de criação: " + creationTime);
System.out.println("Data da última modificação: " + lastModifiedTime);
} catch (IOException e) {
System.out.println("Erro ao obter atributos: " + e.getMessage());
}
Verificando permissões de acesso
File
System.out.println("Pode ler? " + file.canRead());
System.out.println("Pode escrever? " + file.canWrite());
System.out.println("Pode executar? " + file.canExecute());
Path + Files
System.out.println("Pode ler? " + Files.isReadable(path));
System.out.println("Pode escrever? " + Files.isWritable(path));
System.out.println("Pode executar? " + Files.isExecutable(path));
Curiosidade: No Windows as permissões são mais limitadas, enquanto em sistemas Unix é possível consultar e alterar muito mais permissões (por exemplo, via atributos POSIX).
4. Erros comuns ao obter informações de arquivos
Erro nº 1: usar File quando o necessário é Path.
Muitos iniciantes continuam usando File porque parece mais simples ou “é assim em todo lugar na internet”. Mas com Path e Files você faz o mesmo de forma mais robusta e moderna.
Erro nº 2: verificar o tipo do objeto apenas com File.
Se você usa apenas file.isFile() e file.isDirectory(), pode deixar passar arquivos “especiais” (links simbólicos, dispositivos). No API moderno existem Files.isRegularFile(path), Files.isDirectory(path) e outras verificações.
Erro nº 3: ignorar exceções.
Os métodos Files.size(path) e Files.readAttributes(...) lançam IOException. Se você não tratar as exceções, o programa cairá na primeira falha de acesso ou se o arquivo desaparecer durante a execução.
Erro nº 4: esperar que o tamanho da pasta possa ser obtido diretamente.
O método Files.size(path) para uma pasta lançará uma exceção. Para obter o tamanho da pasta, é preciso somar recursivamente os tamanhos de todos os arquivos dentro dela.
Erro nº 5: checar permissões de forma insuficiente.
Mesmo que o arquivo exista, você pode não ter permissão de leitura ou escrita. Sempre verifique as permissões antes das operações: Files.isReadable(path), Files.isWritable(path), Files.isExecutable(path).
GO TO FULL VERSION