In the bad old days. you had to turn anInputStreamReader
into aBufferedReader
if you had the desire to read lines of text. Java 5 introduced theScanner
class, and I never looked back. But theScanner
class is getting no respect. Java 8 makes you use aBufferedReader
, with all that layering nonsense, if you want a stream of lines from a URL. Why not aScanner
? Or, ifBufferedReader
is so loved, why not add a few constructors?
Do you remember the olden days when reading lines from a file was as easy as eating soup with a fork?
BufferedReader reader = new BufferedReader(new InputStreamReader(someInputStream)); String line; while ((line = reader.readLine()) != null) process(line);
Just about ten years ago, Java 5 put an end to that nonsense.
Scanner in = new Scanner(/*just about anything at all that makes sense here */) while (in.hasNextLine()) process(in.nextLine());
Right now, I am putting the final touches on "Java 8 for the Impatient" and I describe the changes in the I/O API. You can read a file into a Stream<String>
. That is nice. The stream is lazy. Once you have found what you are looking for, nothing else is read.
try (Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8)) { String passwordEntry = lines.filter(s -> s.startsWith("password=")).findFirst(); ... }
What if you want to read from an URL instead? Did they retrofit Scanner
? No sir. Scanners lives in vain, in the java.util package
. (Extra credit if you know where that comes from.) Instead, someone went back into the graveyard and retrofitted BufferedReader
. Does BufferedReader
have a constructor that takes an InputStream
? No sir. It hasn't been touched for ten years. So, here we are, in 2013, and have to write
try (Stream<String> lines = new BufferedReader(new InputStreamReader(url.openStream())).lines()) ...
I realize the Java API is vast, but really, it isn't that vast. All the file stuff is in java.io
and java.nio
, and yes, java.util.Scanner
, and every year or two I get to revisit it as I update a book. If I can keep track of it, so should the folks at Oracle. Moving forward, it would be good to keep a few principles in mind.
Files
. Keep them coming.new BufferedReader(new InputStreamReader(...))
. That was a bad idea from the start, and I said so almost twenty years ago in the early editions of Core Java, where I pointed out that for the preceding twenty years programmers had been able to open files and got buffering behind the scenes without any of that nonsense.ReadableByteChannel
. That is how it should be. If you feel the urge to ignore Scanner
and resurrect BufferedReader
, just add those constructors.