Skip navigation
ANNOUNCEMENT: is currently Read only due to planned upgrade until 29-Sep-2020 9:30 AM Pacific Time. Any changes made during Read only mode will be lost and will need to be re-entered when the application is back read/write.

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)
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())
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 retrofitScanner? 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. DoesBufferedReader have a constructor that takes anInputStream? 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 andjava.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. 
  • Everyone loves the convenience methods in FilesKeep them coming.
  • Nobody loves the layered stuff, like 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.
  • Maybe the age of scanners has come to an end, and streams are the new way for consuming input. But learn from the scanners. One thing that made them attractive was that they are omnivores. You could construct them from a file. An input stream. A string. AReadableByteChannel. That is how it should be. If you feel the urge to ignore Scanner and resurrectBufferedReader, just add those constructors.