Read data from a file and save to a Set, but Set is null

Asked

Viewed 133 times

0

I’m trying to read a txt file, select a specific column called "customerid", take all the values from that column and show on the screen how many different values there are.

But when I try to do that, HashSet always returns me value null. I can’t understand what my mistake is or where I’m not loading the data correctly. Can anyone help me?

Code:

package com.nayana.exercicio1.methods;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;

import java.util.HashSet;


public class Methods {

    private BufferedReader file;
    private HashSet<String> customer;
    private int lines;
    private String[] columns;
    public String line;


    //INPUT PARA O ARQUIVOO A SER LIDO

    public BufferedReader getFile() {
        return file;
    }


    public void setFile(BufferedReader file) throws FileNotFoundException {
        this.file = file;
    }

    //CONTAR NÚMERO DE LINHAS EXISTENTES
    public int getLines() {
        return lines;
    }

    public String getLine() {
        return line;
    }
    public void setLines(int lines) throws IOException {
        this.lines = lines;
        }

    public String[] getColumns() {
        return columns;
    }

    public void setColumns(String[] columns) {
        this.columns = columns;
        columns = ((String)line).split(";");
    }
    public void setLine(String line) throws IOException {
        this.line = file.readLine();
    }


    public void contarLinhas() throws Exception {

        while((line = file.readLine()) !=null) {

            setColumns(columns);
            lines++;

        }}



    //CONTAR QUANTOS COSTUMERID DIFERENTES EXISTEM

    public  HashSet<String> getCustomer() {
        return customer;
    }

    public void setCustomer(HashSet<String> customer) throws IOException {
        this.customer =  new HashSet<String>();



    }

    public void customerId() throws Exception {
        setFile(file);
        while((line = file.readLine()) !=null) {
            String [] columns = line.split(";");


            customer.add(columns[4]); 

            customer.size();
        setCustomer(customer);
        }
    }

    //SALTAR LINHA

    public void saltarLinha() throws IOException {
        line = file.readLine();

    }


    //MOSTRAR NA TELA


    public void status(){
    System.out.println("\nO número total de linhas é: " + getLines());
    System.out.println("\nO número total de CustomerId é: " + getCustomer());
    }

Main:

package com.nayana.exercicio1;


import java.io.BufferedReader;
import java.io.FileReader;


import com.nayana.exercicio1.methods.Methods;



public class Exercicio1 {

    public static void main(String[] args) throws Exception {

        Methods exercicio = new Methods();

        exercicio.setFile(new BufferedReader(new FileReader("C:\\Users\\nayan\\Downloads\\orders_04_20_07.txt")));

        exercicio.contarLinhas();
        exercicio.saltarLinha();
        exercicio.customerId();
        exercicio.status();

    }

}

1 answer

1


There are several problems in the code, among them:

  • you try to read the file twice (one in the method contarLinhas and another in the method customerId). The problem is that the first time already reads the whole file, and the second time there will be nothing else to be read
  • in the method contarLinhas you do setColumns(columns), but this columns that you are passing is the field columns of the class itself (i.e., you try to assign it to itself). And the big problem is that at no time it is initialized, so it will be null.

But I think the main problem is the structure of the class itself. Not everything needs to be a field, not everything needs to be getter and Setter, and the file reading process doesn’t have to be so "modularized" so. A suggestion would be to leave the code like this:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

public class Methods {

    private Set<String> customers = new HashSet<>();

    private int lines = 0;

    public void lerArquivo(String arquivo) throws IOException {
        try (BufferedReader reader = new BufferedReader(new FileReader(arquivo))) {
            while (reader.ready()) {
                String line = reader.readLine();
                String[] columns = line.split(";");
                this.customers.add(columns[4]);
                this.lines++;
            }
        }
    }

    public void status() {
        System.out.println("\nO número total de linhas é: " + this.lines);
        System.out.println("\nO número total de CustomerId é: " + this.customers.size());
    }
}

And in the main, do:

public static void main(String[] args) throws Exception {
    Methods exercicio = new Methods();
    exercicio.lerArquivo("C:\\Users\\nayan\\Downloads\\orders_04_20_07.txt");
    exercicio.status();
}

Note that only lines and customers need to be class fields, the rest is only used in the method that reads the file (nor does the file itself need a Setter, is an exaggeration - actually it’s just unnecessary anyway). I initialize these fields in the statement itself, but nothing prevents it from being done in a builder also. And note that I changed the name to customers (plural), since it may have more than one (it may seem a silly detail, but Significant names help when programming).

Note that I also used Try-with-Resources, that closes the file automatically at the end (valid syntax for Java >= 7). I just didn’t put a block catch by "laziness" (lie, was to make the example simpler, since the purpose is more didactic...), but can also put if you want to treat any read error in the file (more on the subject here).

In reading, I fill out the Set of customers and count the lines in the same loop (there is no need to go through the file twice for that). It is also worth noting that customers.add adds the new information on Set, You don’t have to be with him all the time setCustomer.

In fact, I removed the getters and setters because at no time it seemed necessary to use them. Within the class itself I can simply use this.lines and this.customers (the this is optional in these cases, since the class itself can see that it refers to the respective field, but I usually use it to make it clear that I am using a field of the class itself).

A class should only expose what is necessary: if the values of lines and customers depend exclusively on the contents of the archive, there is no reason to have setters that can change the values of these fields to anything. What if the only way to verify their values is through the method status(), doesn’t need getters also.

  • 1

    Man, thank you so much. I was banging my head for a long time to understand, but really when we are beginners we complicate too much something that is even very simple. I am very grateful for the availability and for all the explanation!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.