Question
Reading a Plain Text File in Java: Common Ways and Differences
Question
I want to read plain text data from a file in Java, such as ASCII text. There seem to be several ways to read and write file data in Java. What are the common ways to read a text file, and what are the differences between them?
Short Answer
By the end of this page, you will understand the main ways to read plain text files in Java, when to use each one, and how they differ in simplicity, performance, and control. You will also see practical examples using BufferedReader, Scanner, and the Files API.
Concept
In Java, reading a plain text file means converting the bytes stored in a file into characters you can work with in your program.
Even if your file contains ASCII text, Java typically handles text using character-based readers rather than raw byte streams. This matters because:
- Files are stored as bytes
- Text is used in Java as characters and
Stringvalues - A character encoding tells Java how to convert bytes into characters
ASCII is a simple encoding, but in modern programs you will often use UTF-8, because it can represent ASCII and much more.
Main ways to read text files in Java
1. BufferedReader
A classic and efficient way to read text line by line.
- Good for large files
- Efficient because it buffers input
- Gives you explicit control
- Common in older and modern Java code
2. Scanner
A convenient way to parse text into tokens, lines, integers, and other values.
- Easy for beginners
- Useful when reading formatted text
- Can split input by spaces or lines
- Usually slower than
BufferedReaderfor large files
3. Files.readString() / Files.readAllLines()
Modern utility methods from java.nio.file.Files.
- Very concise
- Great for small and medium files
Mental Model
Think of a text file like a long roll of paper.
BufferedReaderis like reading the roll one line at a time with a steady pace.Scanneris like reading the roll and breaking it into words or numbers for you.Files.readAllLines()is like unrolling the entire paper onto a table so you can inspect everything at once.Files.lines()is like having an assistant hand you one line at a time only when you ask for it.
Another important idea: the file itself stores bytes, but you want text. Encoding is the translator between those two worlds.
Syntax and Examples
1. Read line by line with BufferedReader
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
public class Main {
public static void main(String[] args) throws IOException {
Path path = Path.of("data.txt");
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
}
This is one of the most common ways to read a text file efficiently.
2. Read with Scanner
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Scanner;
{
IOException {
Path.of();
( (path, StandardCharsets.UTF_8)) {
(scanner.hasNextLine()) {
scanner.nextLine();
System.out.println(line);
}
}
}
}
Step by Step Execution
Consider this file data.txt:
Apple
Banana
Cherry
Now this program:
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
public class Main {
public static void main(String[] args) throws IOException {
Path path = Path.of("data.txt");
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println("Read: " + line);
}
}
}
}
What happens step by step
-
Path path = Path.of("data.txt");- Creates a
Pathobject pointing to the file.
- Creates a
Real World Use Cases
Common practical uses
Reading configuration files
Programs often load text settings from files such as:
- app settings
- environment-specific configuration
- simple key-value files
Importing CSV or log files
Applications often read text files line by line to process:
- server logs
- CSV exports
- transaction records
- reports
Reading templates or static content
Programs may load:
- email templates
- SQL scripts
- text resources
- documentation snippets
Parsing command output or generated text
Some tools save text output to files that another Java program reads and processes.
Data cleaning scripts
Small Java utilities often read text files, transform each line, and write a cleaned version back out.
Real Codebase Usage
In real projects, developers usually pick the file-reading approach based on the shape of the problem.
Common patterns
Guard clauses for file checks
Path path = Path.of("data.txt");
if (!Files.exists(path)) {
throw new IllegalArgumentException("File does not exist: " + path);
}
This avoids trying to read a missing file.
Explicit encoding
String text = Files.readString(path, StandardCharsets.UTF_8);
Real code should usually avoid relying on the platform default encoding.
Line-by-line validation
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
String line;
while ((line = reader.readLine()) != null) {
if (line.isBlank()) {
continue;
}
System.out.println("Valid line: " + line);
}
}
This is common when processing user-supplied files.
Stream processing
Common Mistakes
1. Forgetting to specify the encoding
Broken example:
BufferedReader reader = Files.newBufferedReader(Path.of("data.txt"));
This may work, but it uses the platform default charset, which can vary.
Better:
BufferedReader reader = Files.newBufferedReader(Path.of("data.txt"), StandardCharsets.UTF_8);
2. Reading a huge file all at once
Broken approach for large files:
String content = Files.readString(Path.of("huge-file.txt"));
This can use too much memory.
Better for large files:
try (BufferedReader reader = Files.newBufferedReader(Path.of("huge-file.txt"), StandardCharsets.UTF_8)) {
String line;
while ((line = reader.readLine()) != null) {
// process one line at a time
}
}
3. Not closing the file
Comparisons
| Approach | Best for | Reads all at once? | Efficient for large files? | Easy to parse tokens? | Notes |
|---|---|---|---|---|---|
BufferedReader | Line-by-line reading | No | Yes | No | Classic, fast, flexible |
Scanner | Simple parsing of words/numbers/lines | No | Usually less efficient | Yes | Beginner-friendly |
Files.readString() | Small text files | Yes | No | No | Very concise |
Files.readAllLines() |
Cheat Sheet
Quick reference
Read line by line
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
Read entire file as a string
String text = Files.readString(path, StandardCharsets.UTF_8);
Read all lines into a list
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
Read using a stream
try (var lines = Files.lines(path, StandardCharsets.UTF_8)) {
lines.forEach(System.out::println);
}
Read with Scanner
try (Scanner scanner = new Scanner(path, StandardCharsets.UTF_8)) {
(scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
}
FAQ
What is the best way to read a text file in Java?
For most line-by-line cases, BufferedReader is a strong default. For small files, Files.readString() is often the simplest.
Should I use BufferedReader or Scanner in Java?
Use BufferedReader for efficient line reading. Use Scanner when you want easy parsing of tokens, numbers, or lines.
How do I read an ASCII file in Java?
Use a text reader and specify StandardCharsets.US_ASCII if you specifically need ASCII:
Files.readString(path, StandardCharsets.US_ASCII);
Can I use UTF-8 for an ASCII file?
Yes. ASCII text is valid UTF-8 text, so UTF_8 usually works perfectly.
Why should I specify a charset when reading files?
Because otherwise Java may use the system default charset, which can differ across machines and cause incorrect text decoding.
What is the difference between readAllLines() and lines()?
readAllLines() loads everything into memory immediately. processes lines lazily through a stream.
Mini Project
Description
Build a small Java program that reads a plain text file of names and prints useful information about it. This project demonstrates multiple text-file reading tasks that appear in real programs: counting lines, skipping blank lines, and processing text safely with an explicit character encoding.
Goal
Create a program that reads a text file, prints each non-blank line, and shows the total number of non-empty lines.
Requirements
- Read a text file using Java.
- Use an explicit charset when opening the file.
- Ignore blank lines.
- Print each non-blank line with a line number.
- Print the total count of non-blank lines at the end.
Keep learning
Related questions
Avoiding Java Code in JSP with JSP 2: EL and JSTL Explained
Learn how to avoid Java scriptlets in JSP 2 using Expression Language and JSTL, with examples, best practices, and common mistakes.
Choosing a @NotNull Annotation in Java: Validation vs Static Analysis
Learn how Java @NotNull annotations differ, when to use each one, and how to choose between validation, IDE hints, and static analysis tools.
Convert a Java Stack Trace to a String
Learn how to convert a Java exception stack trace to a string using StringWriter and PrintWriter, with examples and common mistakes.