Lendo e Manipulando arquivos CSV com Java

Olá hoje veremos como realizar a leitura e manipulação de arquivos CSV com Java, mostrando que as novas versões da plataforma Java deixaram algumas tarefas simples de serem realizadas.


Exemplo de Arquivo

Hoje em dia é comum ao realizar integrações ou carga de dados o uso de arquivos CSV, isto porque, este arquivo possui uma estrutura de fácil entendimento e simples de manipular na maioria das plataformas de desenvolvimento.

Para realizar a leitura dos dados vamos manipular um arquivo com as seguintes colunas: namecpfagephone address:

name;cpf;age;phone;address
caio;123456789;20;1145223643;Avenida Paulista
vinicius;147852369;18;1125253625;Avenida Manoel
sandra;963258741;30;1174587858;Rua Teixeira
regina;125478522;40;1145254536;Rua Fernando 
fernando;785245563;42;1145253669;Rua Pereira
augusto;456123014;50;1125363633;Avenida Paulinia
maria;456123789;10;1125455525;Avenida Nossa Senhora

Para representar os dados em objetos Java iremos utilizar a seguinte classe:

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

@Getter
@ToString
@AllArgsConstructor
public class User {
 
 private String name, cpf;
 private Integer age;
 private String phone, address;
}

Realizando a Leitura do Arquivo

Para entender o processo de leitura do arquivo, vamos começar apenas exibindo os dados existentes, neste tutorial iremos utilizar a classes Files, que faz parte da NIO API da plataforma Java:

Files.lines(Paths.get("file.csv"))
     .forEach(System.out::println);

O Resultado desse trecho de código será o abaixo:

name;cpf;age;phone;address
caio;123456789;20;1145223643;Avenida Paulista
vinicius;147852369;18;1125253625;Avenida Manoel
sandra;963258741;30;1174587858;Rua Teixeira
regina;125478522;40;1145254536;Rua Fernando 
fernando;785245563;42;1145253669;Rua Pereira
augusto;456123014;50;1125363633;Avenida Paulinia
maria;456123789;10;1125455525;Avenida Nossa Senhora

Perceba que para lermos o conteúdo do arquivo o processo é muito simples, apenas utilizamos o método Files.lines, passando como argumento o Path do arquivo, após este processo podemos manipular o Stream<String> da forma que nosso programa necessita.

O Segundo passo da leitura será a remoção do cabeçalho do arquivo, isto porque, na maioria das importações oque realmente importa são os valores, vamos analisar como ficará o código:


Files.lines(Paths.get("file.csv"))
     .skip(1)
     .forEach(System.out::println);

Aqui foi adicionado ao pipeline a operação skip(1), que faz o primeiro item do Stream ser removido, sendo a linha contendo as informações de cabeçalho do arquivo:

caio;123456789;20;1145223643;Avenida Paulista
vinicius;147852369;18;1125253625;Avenida Manoel
sandra;963258741;30;1174587858;Rua Teixeira
regina;125478522;40;1145254536;Rua Fernando 
fernando;785245563;42;1145253669;Rua Pereira
augusto;456123014;50;1125363633;Avenida Paulinia
maria;456123789;10;1125455525;Avenida Nossa Senhora

Realizando conversões e lógicas com Stream API

Agora vamos adicionar a leitura do arquivo algumas operações mais complexas, a primeira será a conversão da linha em um Objeto do tipo User:


1
2
3
4
5
Files.lines(Paths.get("file.csv"))
     .skip(1)
     .map(line -> line.split(";"))
     .map(col-> new User(col[0], col[1], Integer.parseInt(col[2]), col[3], col[4]))
     .forEach(System.out::println);

Aqui utilizamos da operação map() da Stream API, que é utilizada para realizar transformações de dados, na linha 3 é realizado a transformação da linha do arquivo em um Array de colunas, isto utilizando o método split(";"), onde o ; é o caractere utilizado como quebra, já na linha 4, passamos os dados do String[] para o construtor da classe User, o resultado será o abaixo:


User(name=caio, cpf=123456789, age=20, phone=1145223643, address=Avenida Paulista)
User(name=vinicius, cpf=147852369, age=18, phone=1125253625, address=Avenida Manoel)
User(name=sandra, cpf=963258741, age=30, phone=1174587858, address=Rua Teixeira)
User(name=regina, cpf=125478522, age=40, phone=1145254536, address=Rua Fernando )
User(name=fernando, cpf=785245563, age=42, phone=1145253669, address=Rua Pereira)
User(name=augusto, cpf=456123014, age=50, phone=1125363633, address=Avenida Paulinia)
User(name=maria, cpf=456123789, age=10, phone=1125455525, address=Avenida Nossa Senhora)

Agora vamos utilizar a Stream API para aplicar alumas lógicas, vamos exibir todos os usuários que tenham mais que 30 anos:

1
2
3
4
5
6
Files.lines(Paths.get("file.csv"))
     .skip(1)
     .map(list -> list.split(";"))
     .map(str -> new User(str[0], str[1], Integer.parseInt(str[2]), str[3], str[4]))
     .filter(usr -> usr.getAge() > 30)
     .forEach(System.out::println);

Aqui utilizamos o operação de filter, onde na linha 5, passamos como parâmetro uma expressão lambda com a regra para exibir apenas objetos User que tenham o getAge() > 30, o resultado será o abaixo:

User(name=regina, cpf=125478522, age=40, phone=1145254536, address=Rua Fernando )
User(name=fernando, cpf=785245563, age=42, phone=1145253669, address=Rua Pereira)
User(name=augusto, cpf=456123014, age=50, phone=1125363633, address=Avenida Paulinia)

Após estes exemplos podemos notar como é simples a leitura de arquivos CSV com Java, vale ressaltar que existem várias outras maneiras e formas de realizar esta leitura, sendo que devemos analisar qual a melhor forma dependendo do tamanho do arquivo, e lógicas que queremos aplicar nos resultados.

Até a próxima.

Código fonte

Referências

Comentários

  1. muito bom. parabens.

    Posso usar a mesma logica para arquivos grandes com mais de 300mb por exemplo?

    ResponderExcluir
    Respostas
    1. Blz Cleriston,

      Então sim você pode usar esta estratégia, principalmente a parte onde usamos Stream e Lambdas para executar o pipeline sobre o arquivo, mas também é interessante analisar outras formas de leitura que talvez sejam mais performáticas que a API NIO para leitura de grandes arquivos, para teste neste mesmo git repository do tutorial, tem um projeto chamado read-files-performance, lá fiz um comparativo de performance no processo de leitura de arquivos com outras APIs.

      Abraços.

      Excluir
  2. Eu consigo utilizar essa logica com spring boot?

    ResponderExcluir
    Respostas
    1. Boa tarde

      Sim consegue, faça uma classe que encapsule a lógica de manipulação do CSV, e a utilize no seu Controller ou na camada que desejar.

      Excluir

Postar um comentário

Popular Posts

Criando arquivos de log com Log4J

Monitorando o Tomcat com Java VisualVM

AngularJS - Formatando Datas com o Filter Date

Injeção de dependências em Java EE usando @Inject, @EJB e @Resource ?

Gerenciamento de Transações com EJB - Parte 2

JBoss AS 7 - Instalação e Configuração

Configurando o arquivo application.properties do SpringBoot

Métodos Utilitários da Classe String

Criando uma Aplicação com Spring Boot e MongoDB