Reading Files in Java is the process of taking data from a permanent storage device and bringing it into the computer's memory (RAM). Java offers multiple ways to do this through the java.io and java.nio packages. Whether you are parsing a configuration file or reading a massive dataset, selecting the correct "Reader" is vital for performance.
There are three primary ways to read text files in Java. Each has a specific strength:
| Class | Best For... | Performance |
|---|---|---|
| Scanner | Parsing tokens (integers, words). Small files. | Slow (Does heavy regex parsing). |
| BufferedReader | Reading large text files line-by-line. | Fast (Uses an 8KB buffer). |
| Files (NIO.2) | Quickly reading small/medium files into a List. | Very Fast (Modern utility). |
The Scanner class is part of java.util. It is great because it can "parse" data. If your file has numbers, you can use nextInt() directly. However, it is quite slow because it uses regular expressions under the hood.
try (Scanner scanner = new Scanner(new File("data.txt"))) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(line);
}
} catch (FileNotFoundException e) { e.printStackTrace(); }
For large files, BufferedReader is the gold standard. It minimizes the number of I/O operations by reading large chunks of the file into memory at once. It provides the readLine() method, which returns null when the end of the file is reached.
If the file is not massive (fits in RAM), you can read the entire thing into a List<String> with just one line of code. This is the cleanest approach for modern Java (8+).
List<String> allLines = Files.readAllLines(Paths.get("info.txt"));
Warning: Do not use this for multi-gigabyte files, as it will throw an OutOfMemoryError.
If you aren't reading text, you shouldn't use a "Reader." Instead, use FileInputStream to read raw bytes.
Characters are stored as bytes on the disk. To read them correctly, you must know the encoding. By default, Java uses the system's default charset, but it is safer to specify UTF-8.
BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);
This program reads a "config.txt" file formatted as key=value and loads it into a HashMap.
Q: Why is BufferedReader faster than Scanner?
A: BufferedReader simply reads characters into a buffer. Scanner uses regular expressions to parse the data, which is a CPU-intensive operation.
Q: What happens if you try to read a file that doesn't exist?
A: It throws a FileNotFoundException (which is a subclass of IOException). Always handle this in a try-catch block.
Q: How can you read a very large file (e.g., 50GB) without crashing?
A: Use a Stream with Files.lines(path). This processes the file lazily (one line at a time) and doesn't load the whole file into memory.
Reading files is about knowing the scale of your data. For simple input, Scanner is fine. For professional, high-performance applications, BufferedReader or the Files utility is the way to go. Always wrap your readers in Try-With-Resources to ensure the "file handle" is released back to the Operating System.