Test frameworks read files constantly: test data in CSV or JSON, configuration, expected results. Java gives you several ways to read a file. This guide shows the ones worth knowing, Scanner, Files and BufferedReader, with examples and when to use each.

Quick Comparison

ApproachBest for
Files.readString(path)Small files you want as one string (JSON payloads, templates)
Files.readAllLines(path)Small files you want as a list of lines
Files.lines(path)Large files processed line by line as a stream
BufferedReaderLarge files, line by line, classic style
ScannerParsing tokens: numbers, words, custom delimiters
Advertisement

Reading a File with Scanner

import java.io.File;
import java.io.FileNotFoundException;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

public class ReadWithScanner {
    public static void main(String[] args) throws FileNotFoundException {
        File file = new File("src/test/resources/users.txt");
        try (Scanner sc = new Scanner(file, StandardCharsets.UTF_8)) {
            while (sc.hasNextLine()) {
                String line = sc.nextLine();
                System.out.println(line);
            }
        }
    }
}

Scanner can also read typed values with nextInt(), nextDouble() and next(), and split on any pattern with useDelimiter(","). It's convenient but slower than the alternatives on large files. Mixing nextInt() with nextLine() is a classic trap: nextInt() leaves the line break behind, so the following nextLine() returns an empty string.

Reading a File with Files (Java 11+)

Path path = Path.of("src/test/resources/payloads/create-user.json");

String json = Files.readString(path);                      // whole file (UTF-8 by default)
List<String> lines = Files.readAllLines(path);             // every line

try (Stream<String> stream = Files.lines(path)) {          // lazily, for big files
    long errors = stream.filter(l -> l.contains("ERROR")).count();
}

These methods throw IOException, a checked exception, so declare it or catch it. Files.lines() keeps the file open until the stream is closed, which is why it's inside try-with-resources.

Reading a File with BufferedReader

try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
}

Example: CSV Test Data for a DataProvider

@DataProvider(name = "logins")
public Object[][] logins() throws IOException {
    List<String> rows = Files.readAllLines(Path.of("src/test/resources/logins.csv"));
    return rows.stream()
            .skip(1)                                  // skip the header row
            .filter(r -> !r.isBlank())
            .map(r -> r.split(",", -1))               // -1 keeps empty trailing fields
            .toArray(Object[][]::new);
}

@Test(dataProvider = "logins")
public void login(String user, String pass, String expected) { ... }

A simple split(",") breaks if values contain commas or quotes; for real CSV files use a library such as OpenCSV or Apache Commons CSV.

Reading Files from the Classpath

Paths like src/test/resources/... work when tests run from the project folder, but not from a packaged JAR. Reading from the classpath works everywhere:

try (InputStream in = getClass().getResourceAsStream("/payloads/create-user.json")) {
    String json = new String(in.readAllBytes(), StandardCharsets.UTF_8);
}

Common Errors

  • FileNotFoundException / NoSuchFileException: the path is relative to the working directory, which differs between your IDE, Maven and Jenkins. Print Path.of(".").toAbsolutePath() or read from the classpath.
  • Garbled characters: the file was read with the wrong charset. Pass StandardCharsets.UTF_8 explicitly; see string encoding in Java.
  • Too many open files: streams and readers weren't closed. Use try-with-resources.

FAQs

What is the best way to read a file in Java?

For small files, Files.readString() or Files.readAllLines(). For large files, Files.lines() or a BufferedReader line by line. Use Scanner when you need to parse numbers or tokens.

How do you read a file line by line in Java?

Use BufferedReader.readLine() in a loop, Scanner.hasNextLine()/nextLine(), or Files.lines(path) as a stream, always inside try-with-resources.

Why does my test find the file in the IDE but not in Jenkins?

Relative paths depend on the working directory, which differs between environments. Read files from the classpath with getResourceAsStream(), or build paths from a known base directory.

Is Scanner slow for reading files?

Slower than BufferedReader or Files because it parses tokens with regular expressions. That's fine for small test-data files, but use BufferedReader or Files.lines() for large ones.