Java BufferedReader: How to Read a File with Example
⚡ Smart Summary
Java BufferedReader reads text from an input stream by buffering characters, which makes line-by-line file reading fast and simple. Wrapping a FileReader inside BufferedReader and looping on readLine until it returns null prints an entire file.
How to read a file in Java?
Java provides several mechanisms to read from a file. The most useful package for this is java.io, whose abstract Reader class defines character-stream reading. java.io.BufferedReader is the concrete subclass used for efficient line-based reading.
What is BufferedReader in Java?
BufferedReader is a Java class that reads text from an input stream, such as a file, by buffering characters so that characters, arrays, and lines are read efficiently. Without buffering, each read request made of a Reader triggers a corresponding read request against the underlying character or byte stream.
It is therefore advisable to wrap BufferedReader around any Reader whose read() operations may be costly, such as FileReader and InputStreamReader. A typical usage passes the file path to the reader as follows:
// Note the doubled backslash: a single \ starts an escape sequence objReader = new BufferedReader(new FileReader("D:\\DukesDiary.txt"));
This loads the file into objReader. You then iterate through the contents of the file and print each line. The while loop in the code below reads the file until it reaches the end of the file.
while ((strCurrentLine = objReader.readLine()) != null) { System.out.println(strCurrentLine); }
strCurrentLine holds the current line, and objReader.readLine() returns a String. The loop therefore keeps iterating for as long as the returned value is not null, and stops on the first null, which signals end of file.
BufferedReader Example
The code below is a complete Java BufferedReader example:
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class ReadFileExample { public static void main(String[] args) { BufferedReader objReader = null; try { String strCurrentLine; objReader = new BufferedReader(new FileReader("D:\\DukesDiary.txt")); while ((strCurrentLine = objReader.readLine()) != null) { System.out.println(strCurrentLine); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (objReader != null) objReader.close(); } catch (IOException ex) { ex.printStackTrace(); } } } }
Note: The finally block matters. It guarantees that objReader.close() runs whether or not an exception was thrown, which releases the underlying file handle and keeps memory management predictable. The nested try inside finally is required because close() itself declares IOException.
BufferedReader JDK7 Example
From JDK 7 onward, try-with-resources removes the finally block entirely. Any resource declared in the parentheses of the try statement is closed automatically when the block exits, in reverse order of creation, even if an exception propagates:
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class ReadFileExample_jdk7 { private static final String FILENAME = "D:\\DukesDiary.txt"; public static void main(String[] args) { try (BufferedReader br = new BufferedReader(new FileReader(FILENAME))) { String strCurrentLine; while ((strCurrentLine = br.readLine()) != null) { System.out.println(strCurrentLine); } } catch (IOException e) { e.printStackTrace(); } } }
This version is shorter and safer, so it is the form to prefer in new code. Reading a file is only one use of the class; the next section compares it with the alternative most beginners reach for first.
BufferedReader vs Scanner: Which to Use
Both classes read text, and beginners often pick one arbitrarily. They solve different problems, and the wrong choice shows up as either clumsy manual parsing or poor throughput once the input grows to thousands of lines. The table below sets them side by side.
| Aspect | BufferedReader | Scanner |
|---|---|---|
| Returns | Whole lines as String | Parsed tokens and primitives |
| Parsing built in | No — you split or convert yourself | Yes — nextInt, nextDouble, nextLine |
| Default buffer | 8192 characters | 1024 characters |
| Speed on large files | Faster | Slower, because of regex tokenizing |
| Thread safety | Synchronized | Not synchronized |
| Best for | Reading large files line by line | Small interactive input needing typed values |
Choose BufferedReader when the goal is to move through a file quickly and handle the text yourself, and Scanner when you want typed values without writing conversion code. Splitting each returned line with the String split method gives BufferedReader most of Scanner’s convenience at higher speed.
How to Read Console Input Using BufferedReader
The same class reads keyboard input, which is useful for small command-line programs and for coding-challenge input. System.in is a byte stream, so it cannot be handed to BufferedReader directly. An InputStreamReader bridges bytes to characters, and BufferedReader then adds efficient line reading on top of that bridge.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class ReadConsoleExample { public static void main(String[] args) throws IOException { // Bridge the System.in byte stream to a character stream try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { System.out.print("Enter your name: "); String name = reader.readLine(); System.out.print("Enter your age: "); // readLine always returns text, so convert it explicitly int age = Integer.parseInt(reader.readLine().trim()); System.out.println("Hello " + name + ", age " + age); } } }
Three details are worth remembering. First, readLine() always returns a String, so numeric input must be converted with Integer.parseInt or similar, and a non-numeric entry throws NumberFormatException — wrap the conversion if the input is untrusted. Second, calling .trim() removes the trailing carriage return that Windows consoles append, a frequent cause of parse failures. Third, avoid closing a reader wrapped around System.in if the program still needs console input later, because closing the wrapper closes the underlying stream permanently for that process.
For programs that read many values, reading one line and splitting it is far faster than calling readLine() repeatedly, since each call crosses into the operating system only when the buffer empties. This is the main reason competitive programmers prefer BufferedReader over Scanner for bulk input.
Even with correct code, a handful of errors appear repeatedly.
Common BufferedReader Errors and How to Fix Them
Most BufferedReader failures come from file paths, resource handling, or character encoding rather than from the reading loop itself. Each error below names its exception and its fix.
- Illegal escape character: the path uses a single backslash, as in
"D:\DukesDiary.txt". Double it to"D:\\DukesDiary.txt", or use a forward slash, which Java accepts on Windows. - FileNotFoundException: the path is relative to the working directory, not the source file. Print
new File(name).getAbsolutePath()to see where Java is actually looking. - NullPointerException on the first read: the reader was never assigned because the constructor threw, and the exception was swallowed. Check the exception handling before the loop.
- Garbled or question-mark characters: the file is UTF-8 but
FileReaderapplied the platform default charset. Pass a charset explicitly, for examplenew InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8). - Stream closed: the reader was closed inside the loop or reused after try-with-resources ended. Open a fresh reader for each pass over the file.

