I’ve been using the following approach to read a file into a string in Java:
private String readFile(String file) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(file));
StringBuilder stringBuilder = new StringBuilder();
String line;
String ls = System.getProperty("line.separator");
try {
while ((line = reader.readLine()) != null) {
stringBuilder.append(line).append(ls);
}
return stringBuilder.toString();
} finally {
reader.close();
}
}
Is there a better or more efficient way to read file to string in Java, possibly using modern APIs?
If you’re using Java 11 or later, the cleanest way to read a file into a string is with Files.readString(). It does everything in a single line and handles the file encoding properly:
import java.nio.file.Files;
import java.nio.file.Path;
import java.io.IOException;
public class FileReaderExample {
public static String readFile(String filePath) throws IOException {
return Files.readString(Path.of(filePath));
}
}
Why is this better?
- No need to manually read line by line.
- It automatically closes the file.
- It’s concise and efficient for modern Java applications.
Caveat:
Files.readString() reads the entire file into memory, so it may not be ideal for very large files.
If you want more control over memory usage, you can use Files.readAllLines(). This method reads the file line by line and stores it in a List before joining it into a single string:
import java.nio.file.Files;
import java.nio.file.Path;
import java.io.IOException;
import java.util.List;
public class FileReaderExample {
public static String readFile(String filePath) throws IOException {
List<String> lines = Files.readAllLines(Path.of(filePath));
return String.join(System.lineSeparator(), lines);
}
}
Why use this?
It doesn’t require a loop.
Keeps lines stored in a list, allowing further processing if needed.
Caveat:
Like Files.readString(), this method loads everything into memory, so for huge files, a streaming approach is better.
For reading large files while keeping memory usage low, you can use Scanner. It reads line by line, which avoids storing the whole file in memory at once:
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class FileReaderExample {
public static String readFile(String filePath) throws IOException {
StringBuilder content = new StringBuilder();
try (Scanner scanner = new Scanner(new File(filePath))) {
while (scanner.hasNextLine()) {
content.append(scanner.nextLine()).append(System.lineSeparator());
}
}
return content.toString();
}
}
Why use this?
- More memory-efficient than Files.readString().
- Works well for very large files.
- Auto-closes the scanner using the try-with-resources approach.
Caveat:
- Doesn’t handle different character encodings as easily as Files.readString().
- Doesn’t include empty lines by default—Scanner.nextLine() skips them unless handled explicitly.