Layouts
Java N.IO Layouts
Praticando
É muito comum em projetos reais sermos solicitados para converter nossos objetos em conteúdo texto para após serem escritos em um arquivo .txt
ou .csv
, e também o inverso, ler as linhas de um arquivo e converter em um ou uma lista de objetos.
Para ilustrar o uso de layouts para geração de arquivos texto utilizando uma linguagem orientada a objetos como o Java, iremos ampliar o contexto do exemplo citado acima:
O nosso sistema já tem disponível dados de contatos com base numa lista de objetos deverivados da classe Cadastro.java
com as características que deverão ser escritas em um arquivo:
public class Cadastro {
String nome;
String sexo;
Long telefone;
LocalDate dataNascimento;
Double valorSugerido;
boolean cliente;
// este construtor é somente para ilustrar este exemplo
// evite propagar esta estratégia ao longo dos seus estudos e projetos
public Contato(String nome, String sexo, Long telefone, LocalDate dataNascimento, Double valorSugerido, boolean cliente) {
this.nome = nome;
this.sexo = sexo;
this.telefone = telefone;
this.dataNascimento = dataNascimento;
this.valorSugerido = valorSugerido;
this.cliente = cliente;
}
//métodos getters para obter os dados dos objetos
}
Delimitado
Um arquivo com layout delimitado utiliza um delimitador (separador de características) diante de uma linha no arquivo. Este delimitador costuma ser ,
vírgula, ;
ponto e vírgula ou |
pipe onde grande maioria dos cenários utilizam o padrão de arquivo .csv
.
Vamos iniciar a conversão da nossa lista de objetos para uma lista de strings com colunas delimitadas utilizando ;
;
public static void escreverLayoutDelimitado(List<Cadastro> cadastros){
System.out.println("***** - LAYOUT DELIMITADO - *****");
try {
StringBuilder conteudo = new StringBuilder();
for (Cadastro cadastro : cadastros) {
conteudo.append(cadastro.getNome() + ";");
conteudo.append(cadastro.getSexo() + ";");
conteudo.append(cadastro.getTelefone() + ";");
conteudo.append(cadastro.getDataNascimento() + ";");
conteudo.append(cadastro.getValorSugerido() + ";");
conteudo.append(cadastro.isCliente());
conteudo.append(System.lineSeparator());
}
System.out.println(conteudo.toString());
Path arquivoDestino = Paths.get("C:\\arquivos\\lista-contatos-modelo-delimitado.csv");
Files.write(arquivoDestino, conteudo.toString().getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE);
}catch (Exception ex){
ex.printStackTrace();
}
}
***** - LAYOUT DELIMITADO - *****
Joemia Giron Lyrio Monnerat;F;8321485886;1984-06-30;35.0;false
Reginaldo Folly Barboza Brito;M;2127056726;1990-03-17;40.0;true
Mariza Gadelha Bastida Carneiro;F;9124168455;1889-08-18;40.0;false
Mirian Venancio Portela Ignacia;M;6832598389;1975-11-21;29.0;true
O conteúdo acima não será mais nenhum mistério para você. 😀
Vamos inverter o nosso cenário? Que tal lermos o arquivo .csv
e gerar os objetos de cadastro?
public static List<Cadastro> lerLayoutDelimitado(){
List<Cadastro> cadastros = new ArrayList<>();
try {
Path arquivoOrigem = Paths.get("C:\\arquivos\\lista-contatos-modelo-delimitado.csv");
List<String> linhas = Files.readAllLines(arquivoOrigem);
// imprimindo cada linha obtida no arquivo
for(String linha:linhas){
String[] colunas = linha.split("\\;"); // -> quebra uma linha em colunas com base no delimitador;
String nome = colunas[0];
String sexo = colunas[1];
Long telefone = Long.valueOf(colunas[2]);
LocalDate dataAniversario = LocalDate.parse(colunas[3]);
Double valorSugerido = Double.valueOf(colunas[4]);
boolean cliente = Boolean.valueOf(colunas[5]);
//criando um novo cadastro e adicionando na lista de acordo com os valores de cada coluna
cadastros.add(new Cadastro(nome,sexo,telefone,dataAniversario,valorSugerido,cliente));
}
}catch (Exception ex){
ex.printStackTrace();
}
// ao retornar a lista de objetos
// você poderá realizar qualquer ação com a lista retornada
return cadastros;
}
Posicional
Um arquivo com layout posicional realiza um controle das colunas com base em um estrutura de comprimento (m,n)
previamente definida resultando em realizar o particionamento (subtring)
dos caracteres em uma linha.
Vamos ilustrar uma simulação de layout posicional que seria aderente ao nosso cenário atual:
Nome | Tam. | Observação |
---|---|---|
Nome | 30 | Preencha com espaço em branco à esquerda ou cortar os caracteres após a posição 30 |
Sexo | 1 | salvar M ou F |
Telefone | 10 | Somente números |
Aniversário | 10 | Salvar no formato dd-MM-aaaa |
Valor Sugerido | 7 | Salvar no formato 0000.00 |
Cliente | 1 | Salvar 1 para true e zero para false |
O Layout acima é somente uma ilustração do que você pode se deparar em projetos reais, a proposta aqui é ter um direcionamento inicial de como interagir em requisitos iguais a estes.Recomandamos se desafiar e implementar layouts mais complexos com requisitos mais bem elaborados como no nosso repositório Conta Rural.
public static void escreverLayoutPosicional(List<Cadastro> cadastros) {
try {
System.out.println("***** - LAYOUT POSICIONAL - *****");
StringBuilder conteudo = new StringBuilder();
for (Cadastro cadastro : cadastros) {
String nome = cadastro.getNome();
// calma, não será assim para sempre
if (nome.length() > 30)
nome = nome.substring(0, 30);
// pesquise sobre String.format
if (nome.length() < 30)
nome = String.format("%-30s", nome);
conteudo.append(nome);
conteudo.append(cadastro.getSexo().toUpperCase());
conteudo.append(cadastro.getTelefone());
conteudo.append(cadastro.getDataNascimento());
DecimalFormat decimalFormat = new DecimalFormat("#0000.00");
String valorFormatado = decimalFormat.format(cadastro.getValorSugerido());
conteudo.append(valorFormatado.replaceAll("\\,", "\\.")); // -> troca , por .
conteudo.append(cadastro.isCliente() ? "1" : "0");
// nova linha
conteudo.append(System.lineSeparator());
}
System.out.println(conteudo.toString());
Path arquivoDestino = Paths.get("C:\\arquivos\\lista-contatos-modelo-posicional.txt");
Files.write(arquivoDestino, conteudo.toString().getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE);
}catch (Exception ex){
ex.printStackTrace();
}
}
***** - LAYOUT POSICIONAL - *****
Joemia Giron Lyrio Monnerat F83214858861984-06-300035.500
Reginaldo Folly Barboza Brito M21270567261990-03-170040.301
Mariza Gadelha Bastida CarneirF91241684551889-08-180040.700
Mirian Venancio Portela IgnaciM68325983891975-11-210029.501
Ler arquivos com layout posicional é muito semelhante ao layout posicional, precisamos obter uma lista de Strings mas desta vez iremos particionar (substring)
cada linha de acordo o comprimento correspondente.
public static List<Cadastro> lerLayoutPosicional(){
List<Cadastro> cadastros = new ArrayList<>();
try {
Path arquivoOrigem = Paths.get("C:\\arquivos\\lista-contatos-modelo-posicional.txt");
List<String> linhas = Files.readAllLines(arquivoOrigem);
// imprimindo cada linha obtida no arquivo
for(String linha:linhas){
String nome = linha.substring(0,30).trim(); // -> pego os caracteres da posição 0 a 30, trim() remove espaços laterias
String sexo = linha.substring(30,31); // observe que sempre o primeiro parâmetro tem o valor que o segundo parâmetro anterior
Long telefone = Long.valueOf(linha.substring(31,41)); // 41-31=10
LocalDate dataAniversario = LocalDate.parse(linha.substring(41,51));
Double valorSugerido = Double.valueOf(linha.substring(51,58));
boolean cliente = linha.substring(58,59).equals("1");
//criando um novo cadastro e adicionando na lista de acordo com os valores de cada coluna
cadastros.add(new Cadastro(nome,sexo,telefone,dataAniversario,valorSugerido,cliente));
}
}catch (Exception ex){
ex.printStackTrace();
}
// ao retornar a lista de objetos
// você poderá realizar qualquer ação com a lista retornada
return cadastros;
}
Java4Business - Live 01
Java4Business - Live 02
Java4Business - Live 03