1

So I have this fairly simple code where I'm trying to read a file line by line:

if(new File(filesDir).listFiles() != null){
    for(File file : new File(filesDir).listFiles()){
        try {
            Stream<String> stream = Files.lines(Paths.get(file.getAbsolutePath()));
            for(int i = 0 ; i < stream.toArray().length; i++){
                System.out.println(stream.toArray()[i]);
            }
            stream.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }   
    }
}

But when it reaches Sysout it throws exception:

Exception in thread "main" java.lang.IllegalStateException: java.lang.IllegalStateException: stream has already been operated upon or closed

Caused by: java.lang.IllegalStateException: stream has already been operated upon or closed

Every example I find uses Lambda expressions, I don't think that's the only way, or is it?

Community
  • 1
  • 1
Artemio Ramirez
  • 1,116
  • 1
  • 10
  • 23

1 Answers1

4

Stream are an alternative to using a loop. You can't use a Stream more than once. Even if you could use a stream more than once calling toArray() twice per line of input would be insanely expensive.

What you can do is

try (Stream<String> stream = Files.lines(file.toPath())) {
    stream.forEach(System.out::println);
}

Note: a significant advantage of using this approach is that it can print the file as it reads it. This means that no matter how big the file is, it can still read it. If you use a collection or an array with every line, the size of file you read will be limited by the amount of memory you have.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • I want to iterate the Stream but not using forEach, is there a way i can accomplish that with a regular for loop? – Artemio Ramirez Apr 21 '16 at 21:31
  • 2
    Well usually you use a stream as a stream, if you want a loop just use a list (if it fits in memory). You can achive it using `java.nio.Files.readAllLines(Path)`. If it does not fit, you can convert a stream into an iterator using `Stream.spliterator()` and from this, you can iterate in regular imperative style. – Dici Apr 21 '16 at 21:41
  • @Dici Actually with Peter explanation of how the Stream works, and a little more research/change on thought i'll stick with the Stream approach, I do feel it is the ideal way to go. – Artemio Ramirez Apr 21 '16 at 21:57
  • @ArtemioRamirez stream are great for data processing, but they have a limitation of single use. – Peter Lawrey Apr 22 '16 at 05:57