I am using Java 8 Streams to create stream from a csv file.
I am using BufferedReader.lines()
, I read the docs for BufferedReader.lines()
:
After execution of the terminal stream operation there are no guarantees that the reader will be at a specific position from which to read the next character or line.
public class Streamy {
public static void main(String args[]) {
Reader reader = null;
BufferedReader breader = null;
try {
reader = new FileReader("refined.csv");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
breader = new BufferedReader(reader);
long l1 = breader.lines().count();
System.out.println("Line Count " + l1); // this works correctly
long l2 = breader.lines().count();
System.out.println("Line Count " + l2); // this gives 0
}
}
It looks like after reading the file for first time, reader does not get to beginning of the file. What is the way around for this problem
It looks like after reading the file for first time, reader does not get to beginning of the file.
No - and I don't know why you would expect it to given the documentation you quoted. Basically, the lines()
method doesn't "rewind" the reader before starting, and may not even be able to. (Imagine the BufferedReader
wraps an InputStreamReader
which wraps a network connection's InputStream
- once you've read the data, it's gone.)
What is the way around for this problem
Two options:
Save the result of lines()
to a List<String>
, so that you're then not reading from the file at all the second time. For example:
List<String> lines = breader.lines().collect(Collectors.toList());
As an aside, I'd strongly recommend using Files.newBufferedReader
instead of FileReader
- the latter always uses the platform default encoding, which isn't generally a good idea.
And for that matter, to load all the lines into a list, you can just use Files.readAllLines
... or Files.lines
if you want the lines as a stream rather than a list. (Note the caveats in the comments, however.)
See more on this question at Stackoverflow