1

I am trying to read a simple text file that looks like this:

operationName1 Value
operationName2 Value

The operation names are strings (there are only two possible operations) and the values are ints.

My goal is to have an array as the output that looks like this:

[[1,10],[2,5]]

In the specified array, I would transform the operationName1 into 1 and operationName2 into 2, with the corresponding value.

This is what I tried:

try{
    Path path = Paths.get("./myFile.txt");
    String[][] array = Files.lines(path)
                    .map(s -> s.split("\\s+", 2))
                    .map(a -> new String[]{a[0], a[1]})
                    .toArray(String[][]::new);

    System.out.println(Arrays.toString(array));
    }catch(IOException e){  
}

I did not change the names to integer in this code, I simply started by trying to get an array of string that I can print to see if I am reading the file correctly.

My output looks like this:

[[Ljava.lang.String;@682a0b20, [Ljava.lang.String;@3d075dc0, [Ljava.lang.String;@214c265e, [Ljava.lang.String;@448139f0, [L ...

Am I only getting a stream instead of strings?

The path is correct, I can read the file normally using standard syntax. But I would really like to understand the new syntax to start on the right foot, as understanding it seems helpful.

My question: Would you have an idea on how can I correct this problem, or even better, an idea on how I could have my expected output using the most recent syntax? (Java 8 if possible?)

PS: I also saw this syntax but I am not sure how to complete it to get my result, and I am not sure if this would be better or worse (but it seems to be Java 8).

Files.lines(Paths.get(ClassLoader.getSystemResource("myFile.txt")
    .toURI())).forEach(System.out::println);
Gordon Allocman
  • 768
  • 7
  • 23
David Gourde
  • 3,709
  • 2
  • 31
  • 65

1 Answers1

5

What you really need is the following

System.out.println(Arrays.deepToString(array));

Otherwise, you're printing each array. And knowing that when calling a print on an array, a sort of reference/hashcode is printed, you get the result from above.

Arrays#deepToString prevents that and prints each element from each array.


The following lines are basically doing the same thing. You should just keep the first one.

Since your lines only contains two values, you do not need the second line.

.map(s -> s.split("\\s+", 2))           returns a Stream<String[]>
.map(a -> new String[]{a[0], a[1]})     returns a Stream<String[]>

Another suggestion would be to use a map object if the values from column one are unique.

Map<String, Integer> map = Stream.of("1 10", "2 5")
                                 .map(x -> x.split(" "))
                                 .collect(Collectors.toMap(a -> String.valueOf(a[0]), 
                                                           a -> Integer.parseInt(a[1])));

Credit to @Tunaki

To avoid a ressources leak, use a try-with-ressources with Files.lines

String[][] array;
try (Stream<String> lines = Files.lines(path)) {
    array = lines.map(s -> s.split("\\s+", 2))
                 .toArray(String[][]::new);
}
Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
  • 3
    I'd also point out that the `Stream` returned by `Files.lines` needs to be closed in a try-with-resources. – Tunaki Mar 29 '16 at 19:48
  • @Tunaki Thanks I'm hesitating. Is this good? – Yassin Hajaj Mar 29 '16 at 19:54
  • 2
    Yes, it's also mentioned in the [doc](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#lines-java.nio.file.Path-): *If timely disposal of file system resources is required, the try-with-resources construct should be used to ensure that the stream's close method is invoked after the stream operations are completed.* – Tunaki Mar 29 '16 at 19:55