Read lines from a TXT to Arraylist

Asked

Viewed 883 times

1

I need to read a log saved in a TXT file that contains geographical coordinates in the following form:

-54.123440,-21.123456
-54.123425,-21.123467
-54.123435,-21.123480
-54.123444,-21.123444
-54.123452,-21.123100

Each line has the longitude and latitude of each coordinate (point of the graph), separated by a comma (,).

I’m going to use these coordinates to generate a graph where each line is a point, so I need to have access to the latitude and longitude of each point. I would like to know how to store the latitude and longitude of each point in one ArrayList, and if that’s really the best way to do that for me to have access to that data to generate the graph afterwards.

I can read the file and print line by line, through the following class:

public class Leitura {

    public void leTXT() {
        Scanner ler = new Scanner(System.in);
        try {
            FileReader arq = new FileReader("c:/dados/log.txt");
            BufferedReader lerArq = new BufferedReader(arq);
            String str = lerArq.readLine();
            while (str != null) {
                System.out.printf("%s\n", str);
                str = lerArq.readLine();
            }
            arq.close();
        } catch (IOException e) {
            System.err.printf("Erro na abertura do arquivo!");
        }

        System.out.println();
    }
}
  • I guess it depends on the graph component you’re going to use, no?

  • "Each line has the latitude and longitude of each coordinate (point of the graph), separated by a comma (,)." - In your case, longitude is actually the first number and latitude is the second.

  • Exactly, I edited the question by fixing the error.

2 answers

4


In your file, each line corresponds to a coordinated and each coordinated has a longitude (between -180 and +180) and a latitude (between -90 and +90). The contents of the archive are coordinate list.

Note that the central concept we have here is a coordinate. Since Java is an object-oriented language, these concepts map to objects that are modeled in classes. So, Coordenada is a class:

public final class Coordenada {
    private final double longitude;
    private final double latitude;

    public Coordenada(double longitude, double latitude) {
        if (longitude < -180.0 || longitude > 180.0) {
            throw new IllegalArgumentException("Longitude inválida.");
        }
        if (latitude < -90.0 || latitude > 90.0) {
            throw new IllegalArgumentException("Latitude inválida.");
        }
        this.longitude = longitude;
        this.latitude = latitude;
    }

    public double getLongitude() {
        return longitude;
    }

    public double getLatitude() {
        return longitude;
    }

    public static Coordenada parse(String linha) {
        String[] partes = linha.split(",");
        if (partes.length != 2) throw new IllegalArgumentException("Linha malformada.");

        double a, b;
        try {
            a = Double.parseDouble(partes[0]);
            b = Double.parseDouble(partes[1]);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Linha malformada.");
        }
        return new Coordenada(a, b);
    }
}

Note this method parse(String). He is responsible for interpreting a line and converting into a coordinate.

You can use the method Files.readAllLines(Path, Charset) to get all the file lines easily.

With that, we can do so:

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Leitura {

    public List<Coordenada> lerCoordenadas() throws IOException {
        return lerCoordenadas(Paths.get("c:/dados/log.txt"));
    }

    public List<Coordenada> lerCoordenadas(Path arquivo) throws IOException {
        return Files.readAllLines(arquivo, StandardCharsets.UTF_8)
               .stream()
               .map(Coordenada::parse)
               .collect(Collectors.toList());
    }
}

In such case, you don’t have to worry about opening, reading and closing the file manually because the Files.readAllLines already does it. But if you do it manually, remember to use the Try-with-Resources.

  • I understood, so for me to have coordinate vector I use a coordinate type arraylist, right?

  • @Brunopadilha You use the List<Coordenada> that the method lerCoordenadas() provides (maybe with a loop for or similar). Although they are very similar, List<Coordenada> and ArrayList<Coordenada> are different concepts. Reasons to invoke the constructor of ArrayList directly exist in heaps, but to use a variable of type ArrayList<...> instead of List<...> there is hardly any.

  • Understood, now it is clear its implementation.

  • One last question, how do I access the values in another class? For example to plot a line in my chart I use linha.drawLine(latitudeP1, longitudeP1, latitudeP1, longitudeP1). I couldn’t access it by instantiating an object Coordenada c = new Coordenada; and subsequently linha.drawLine(c.getLatitude, c.getLongitude, c2.getLatitude, c2.getLongitude).

  • @Brunopadilha I don’t know if I understand what you’re asking now. Looking at the code of your comment, the parentheses were missing after the getLatitude and the getLongitude and also the parameters of the Coordenada. However, if it is something more complicated than that, I suggest creating a new question by putting there the full code and a link to that question here, and then call me to take a look.

  • Created a new question to try to explain my doubt.

Show 1 more comment

0

Without knowing which graphic library you will use, here is a generic solution, which uses a Map to store the latitude set / longitude.

public HashMap<Double, Double> getCoordenadas() throws IOException{     

    HashMap<Double, Double> retorno = new HashMap<>();

    List<String> linhas = Files.readAllLines(Paths.get("C:\\dados\\log.txt"));

    for (String linha : linhas) {
        String[] coordenadas = linha.split(",");
        retorno.put(Double.valueOf(coordenadas[0]), Double.valueOf(coordenadas[1]));
    }

    return retorno;
}

Note that I used a different method to read the file, the class Files.

If your project uses Java 8, I recommend using it, because as you can see, it greatly decreases the complexity of the code.

  • If there are two or more points with the same longitude, but with different latitudes, what happens?

  • The graph will plot all points, if they are equal points the drawing will be superimposed.

Browser other questions tagged

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