Reputation: 65
I have a weird problem, where my code seems fine (for me at least), yet on the debugger and actual result is always wrong.
Firstly the code:
private void updateRegistry( String filename ){
BufferedReader database = Init.MANAGER.readFile( Path.getDB(), filename );
REGISTRY.clear();
long maxLines = database.lines().count();
for (int i = 0; i < maxLines; i++) {
try {
String currentLine = database.readLine();
Registry regAdd = new Entry( currentLine );
REGISTRY.add( regAdd );
} catch( Exception e ) {
System.err.println( ERROR.getStackTrace( e ) );
}
}
}
So, all currentLine
variables in the loop always returns null
.
Being the REGISTRY
a constant on the class which is a LinkedList
.
And ERROR
another constant to report errors, which is not relevant.
I'm aware of .readLine()
that reads a line per method call, making each call the next line to be read.
Also, by using the debugger, I can confirm the data is being recovered in the BufferedReader
variable.
Yet the .readLine()
method returns null. I have no idea what the problem is.
My only guess is the .lines()
that I used to count them. Does that make the stream null? If this is the problem, how can I correct it, since I need the line count.
What am I doing wrong? I debugged this a hundred times, nothing I do gives me the data.
For future reference, I used the example of this other post, which I prefer more than the while loop. After removing the .lines()
variable and the loop
private void updateRegistry( String filename ){
BufferedReader database = Init.MANAGER.readFile( Path.getDB(), filename );
REGISTRY.clear();
try {
for ( String currentLine = database.readLine(); currentLine != null; currentLine = database.readLine() ) {
Registry regAdd = new Registry( currentLine );
REGISTRY.add( regAdd );
}
} catch ( Exception e ){
System.err.println( ERROR.getStackTrace( e ) );
}
}
Thanks for the help, now I can finish my work assignment faster! xD
As, now my best friend, Holger mentioned, gonna use the stream loop directly, which makes it even neater.
database.lines().forEach(currentLine -> REGISTRY.add(new Entry(currentLine)));
And an one liner! Beautiful! Gonna dwelve on the stream world after this.
Upvotes: 1
Views: 1252
Reputation: 298163
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.
Thus, after invoking long maxLines = database.lines().count();
, there is no guaranty that you can read any lines from the same reader afterwards. In typical implementations, this operation consumes all lines.
If you can’t re-acquire an equivalent reader, but really need the count beforehand, the only option is to buffer them, e.g. to collect all lines into a List
like
List<String> list=database.lines().collect(Collectors.toList());
to get the size and the contents.
If you don’t need the count beforehand, you can replace the counting operation with your actual operation:
database.lines().forEach(currentLine -> REGISTRY.add(new Entry(currentLine));
As danmec has pointed out, even without the stream API, you don’t need the count beforehand, when all you want to do with it, is performing the iteration.
Upvotes: 3
Reputation: 2250
BufferedReader.lines()
is a new method in Java 8 which I'm not too familiar with. However, since you just want to process each line in turn, you would typically use something like this:
String currentLine = null;
while ((currentLine = database.readLine()) != null) {
// do processing
}
Upvotes: 3