3

I have a file with some data separated by semicolon. I'm trying to build a stream, which will read file line by line, separate every column of data and map it to new object.

data.txt:

John;Smith;42;shopassistant
Clara;Lefleur;24;programmer

Person.class:

public class Person{
   String name;
   String lastName;
   int age;
   String job;
}

I started with something like this:

List<Person> people = Files.lines(Paths.get("src/data.txt"))....

Any ideas?

YCF_L
  • 49,027
  • 13
  • 75
  • 115
steve1337
  • 355
  • 1
  • 7
  • Possible duplicate of [Read CSV with Scanner()](https://stackoverflow.com/questions/14274259/read-csv-with-scanner) –  Aug 24 '18 at 18:00

2 Answers2

5

You can use map like so :

List<Person> people = Files.lines(Paths.get("src/data.txt"))
        .map(p -> p.split(";"))//split each line with ';'
        .map(p -> new Person(p[0], p[1], Integer.valueOf(p[2]), p[3]))//create a new Person
        .collect(Collectors.toList());//then collect the result

Make sure that you have a constructor which hold that information :

public Person(String name, String lastName, int age, String job) {
YCF_L
  • 49,027
  • 13
  • 75
  • 115
  • 1
    Great solution. I didn't know how stream behaves after .map method and didn't find out that I could use it twice. Thanks. – steve1337 Aug 24 '18 at 18:11
  • You are welcome @steve1337, because map return a `Stream` so you can use another map, and so on – YCF_L Aug 24 '18 at 18:13
  • @YCF_L [FYI this can be done nicer with java-9 and Scanner](https://stackoverflow.com/a/52017044/1059372) – Eugene Aug 25 '18 at 11:51
  • @Eugene yes If the user use Java-9+ but I like to use `Files` as I can use `takeWhile`, `dropWhile` and many other better tools +1 any way – YCF_L Aug 25 '18 at 11:57
  • @YCF_L and btw you got lucky here with a single char regex, otherwise that `Pattern` should have been taken outside the stream per-se... – Eugene Aug 25 '18 at 12:05
  • @Eugene I test both code mine and yours I found that my code is more quick, you can check that in your own environment – YCF_L Aug 25 '18 at 12:24
  • @YCF_L *test both code mine and yours I found that my code is more quick*, sorry but that is like saying nothing, proper tests and proper explanation of them is a lot harder than me and you might think – Eugene Aug 25 '18 at 12:25
2

A Scanner would be more useful for this job, and since java-9 this is much nicer to work with:

Pattern p = Pattern.compile("^(\\w+);(\\w+);(\\w+);(\\w+)$", Pattern.MULTILINE);
List<Person> persons = new Scanner(Paths.get("src/data.txt"))
            .findAll(p)
            .map(mr -> new Person(mr.group(1), mr.group(2), Integer.valueOf(mr.group(3)), mr.group(4)))
            .collect(Collectors.toList());
Eugene
  • 102,901
  • 10
  • 149
  • 252