Lendo N arquivos .txt a partir de um diretório
Nesse post veremos como realizar a leitura de N arquivos .txt a partir de um diretório inicial.
Problemática
A problemática desse post é a seguinte:
Dado um diretório inicial, realize a leitura de todos os arquivos com a extensão .txt. Ao final da execução, o programa deve exibir o caminho dos arquivos.txt e seus respectivos conteúdos.
Solução Técnica
Para solucionar o problema iremos criar uma aplicação em Java, que irá realizar a leitura dos arquivos e armazenar as informações em um HashSet.
Mão na massa
Primeiro de tudo vamos criar nosso arquivo main.java, que será responsável por iniciar a aplicação, solicitando ao usuário o diretório inicial da leitura dos arquivos, como no exemplo abaixo:
import javax.swing.*;
import java.io.File;
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
String mainFolder = JOptionPane.showInputDialog("Enter the starting directory for the phone search.");
File mainDirectory = new File(mainFolder);
DirectorySearch directorySearch = new DirectorySearch();
HashSet<String> itens = directorySearch.search(new HashSet<>(), mainDirectory);
itens.forEach(System.out::println);
}
}
A partir do nosso Main.java, vamos para a classe DirectorySearch.java, essa responsável por acessar cada subpasta e identificar o conteúdo da PASTA.
import item.ItemFactory;
import item.ItemSearch;
import java.io.File;
import java.util.HashSet;
public class DirectorySearch {
private final ItemSearch itemSearch;
public DirectorySearch(){
itemSearch = new ItemFactory().getImplementation();
}
public HashSet<String> search(HashSet<String> itens, File mainDirectory) {
File[] directoryItens = mainDirectory.listFiles();
if(directoryItens != null) {
searchItens(itens, directoryItens);
}
return itens;
}
private void searchItens(HashSet<String> itens, File[] directoryItens){
for (File item : directoryItens) {
if (item.isDirectory()) {
search(itens, item);
} else {
itens.addAll(itemSearch.getValue(item));
}
}
}
}
Agora que conseguimos navegar por todos os diretórios e sub-diretórios, precisamos realizar o filtro dos arquivos para fazermos as leituras somente dos arquivos .txt.
Para isso, vamos criar uma interface de contrato e a implementação para o uso com .txt. Se precisamos criar para outro tipo de arquivo no futuro, ficará mais simples de alterar.
package item;
import java.io.File;
import java.util.HashSet;
public interface ItemSearch {
HashSet<String> getValue(File item);
}
Implementação:
public class ItemText implements ItemSearch {
private final String allowedExtension = "txt";
public HashSet<String> getValue(File file) {
return readFile(file);
}
private HashSet<String> readFile(File file){
if(isValidFile(file)){
return getText(file);
}
return new HashSet<>();
}
private HashSet<String> getText(File file) {
HashSet<String> texts = new HashSet<>();
try {
List<String> fileLines = Files.readAllLines(file.toPath());
fileLines.parallelStream().forEach(texts::add);
} catch (IOException e) {
System.out.println("Error to read file: "+file.getPath());
e.printStackTrace();
}
return texts;
}
private boolean isValidFile(File file){
String fileExtension = FilenameUtils.getExtension(file.getName());
return allowedExtension.equalsIgnoreCase(fileExtension);
}
}
Também vamos criar um ItemFactory para ser responsável por criar nosso objeto que fará a leitura dos arquivos.
public class ItemFactory {
private ItemText itemText;
public ItemSearch getImplementation(){
if(itemText == null){
itemText = new ItemText();
}
return itemText;
}
}
Conclusão
Pronto! Agora basta executar nosso método main e será solicitado o diretório inicial. A partir dele a aplicação irá realizar a leitura de todos os arquivos .txt no diretório e subdiretórios.
Claro que você pode conferir o projeto no nosso github!