Table of Contents
Back to Blog

Java Deep Dive

How to Count Lines in a File Using Java (6 Methods, Benchmarked)

Count lines in a file using Java — BufferedReader, Files.lines, LineNumberReader, BufferedInputStream, and more. Includes benchmark results for 5GB files and Java 8–17 examples.

Java 7+Java 8+Java 17
Published: May 12, 2026Updated: May 12, 202616 min readAuthor: Line Counter Editorial Team
JavaFile I/OPerformanceSpring BootTutorial

You are processing a 3GB log file in a Spring Boot service. You call Files.readAllLines(path), the same method you have used for small config files, and the JVM crashes with OutOfMemoryError.

Or you use LineNumberReader.getLineNumber() and wonder why the number is not the total file size until after you read the entire file.

Java has several ways to count lines in a file. They do not have the same memory profile, version support, encoding behavior, or performance. This guide shows when to use each method and which ones to avoid in production.

If you only need a quick count outside a Java application, use the browser-based Line Counter tool. If you are building the behavior into a Java service, keep reading.

Quick Method Guide

Choose a method

MethodJavaLarge filesBest use
Files.lines().count()8+SafeModern default
BufferedReader7+SafeLegacy compatibility
LineNumberReader7+SafeCurrent line tracking
BufferedInputStream7+FastestHuge files
Files.readAllLines()7+DangerousTiny files only
Apache Commons IOdependencySafeExisting Commons projects

For most java count lines file work in Java 8+, use Files.lines() and close the stream. For Java 7, use BufferedReader. For java count lines large file jobs where speed matters, use byte scanning. If your search was "count lines in a file java" and you just need one answer, start with Files.lines().count().

Method 1: Files.lines() — The Modern Java 8+ Approach

Use this when

You are on Java 8+ and want the cleanest production-friendly answer.

Watch out

Files.lines java code must close the returned Stream because it is backed by an open file.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;

public class LineCounter {
    public static long countLines(Path path) throws IOException {
        try (Stream<String> lines = Files.lines(path)) {
            return lines.count();
        }
    }
}

This is the best general-purpose answer to count lines in a file java projects on Java 8 and newer. It is lazy, memory-safe, and concise. In other words, Files.lines java code is the modern default for java count lines file utilities.

For java count lines file helpers that will live in a shared library, Files.lines java code also makes the resource boundary obvious: open the stream, count it, close it.

Do not write this:

long count = Files.lines(path).count(); // file handle can remain open

The Java Stream documentation notes that streams backed by I/O channels require closing. Files.lines java examples should always use try-with-resources, especially in services that may count many uploaded files.

Encoding

Always specify the encoding when the input is not guaranteed to be UTF-8.

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

try (Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8)) {
    return lines.count();
}

try (Stream<String> lines = Files.lines(path, Charset.forName("GBK"))) {
    return lines.count();
}

For UTF-8 files with a BOM, remove the BOM from the first line only if your downstream logic cares about content. The line count is normally unaffected, so Files.lines java counting remains correct.

try (Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8)) {
    return lines
        .map(line -> line.startsWith("\uFEFF") ? line.substring(1) : line)
        .count();
}

Do not add parallel()

long count = Files.lines(path).parallel().count();

That looks faster, but it usually is not. File reading is I/O-bound, and parallel streams add coordination overhead without making one disk read the file in parallel. For java 8 count lines code, keep Files.lines() sequential unless your benchmark proves otherwise. This is one of the few places where Files.lines java examples should be boring on purpose.

Method 2: BufferedReader — The Classic Java 7+ Approach

Use this when

You need Java 7 compatibility or prefer explicit line-by-line code.

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

public static long countLinesBufferedReader(String filePath) throws IOException {
    long lines = 0;
    try (BufferedReader reader = new BufferedReader(
            new InputStreamReader(new FileInputStream(filePath), StandardCharsets.UTF_8))) {
        while (reader.readLine() != null) {
            lines++;
        }
    }
    return lines;
}

This BufferedReader count lines method is reliable, readable, and safe for large files. It creates one String per line, so it is not the fastest possible approach, but it is a strong default for Java 7 and enterprise codebases. If you need BufferedReader count lines code that works before Java 8 streams, this is the version to copy.

You can tune the buffer:

BufferedReader reader = new BufferedReader(
    new InputStreamReader(new FileInputStream(filePath), StandardCharsets.UTF_8),
    64 * 1024
);

Increasing the buffer can help large sequential reads, but benchmark before locking in a value. For most services, the default buffer is fine. The BufferedReader count lines pattern is usually fast enough unless you are scanning multi-GB logs repeatedly.

Method 3: LineNumberReader — Useful, but Easy to Misread

Important correction

LineNumberReader is not a magic total-line API. It reports the current line number after reading. You must consume the whole file before using it as a count.

import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

public static int countLinesLineNumberReader(String filePath) throws IOException {
    try (LineNumberReader reader = new LineNumberReader(new FileReader(filePath))) {
        while (reader.readLine() != null) {
            // consume the file
        }
        return reader.getLineNumber();
    }
}

The real trap is calling getLineNumber() too early:

try (LineNumberReader reader = new LineNumberReader(new FileReader(filePath))) {
    return reader.getLineNumber(); // always starts at 0
}

The Java documentation describes LineNumberReader as a reader that tracks the current line number. It is useful when you need diagnostics such as "error at line 123." It is less useful as a dedicated file-counting method.

Two limitations matter:

  • It returns int, not long.
  • It still reads the entire file, just like BufferedReader.

For most java count lines file code, prefer Files.lines() or BufferedReader unless you also need current-line tracking.

Method 4: BufferedInputStream — Fastest for Large Files

Use this when

You need java count lines large file performance and only care about physical newline-delimited lines.

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public static long countLinesFast(String filePath) throws IOException {
    long lines = 0;
    boolean sawAnyByte = false;
    boolean endsWithoutNewline = false;

    try (InputStream input = new BufferedInputStream(new FileInputStream(filePath), 1024 * 1024)) {
        byte[] buffer = new byte[1024 * 1024];
        int bytesRead;

        while ((bytesRead = input.read(buffer)) != -1) {
            sawAnyByte = true;
            for (int i = 0; i < bytesRead; i++) {
                if (buffer[i] == '\n') {
                    lines++;
                }
            }
            endsWithoutNewline = buffer[bytesRead - 1] != '\n';
        }
    }

    if (sawAnyByte && endsWithoutNewline) {
        lines++;
    }
    return lines;
}

This is usually the fastest java count lines large file method because it avoids creating String objects. It just scans bytes for '\n'. When people ask for java count lines large file performance, this is the method to benchmark against.

That speed comes with tradeoffs:

  • It counts physical newline-delimited lines, not decoded text lines.
  • It does not validate encoding.
  • It is lower-level and easier to get wrong.

For UTF-8, ASCII, and typical log files, this is exactly what you want. For records with custom line separators, use a reader-based method.

Method 5: Files.readAllLines() — Only for Small Files

Production warning

Files.readAllLines() loads the entire file into memory. Do not use it when file size is unknown.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

public static int countLinesUnsafe(Path path) throws IOException {
    List<String> lines = Files.readAllLines(path);
    return lines.size();
}

This is fine for a tiny test fixture or a 20-line config file. It is dangerous for logs, CSV exports, data dumps, and uploads. A 2GB file can require far more than 2GB of heap once decoded text, String objects, arrays, and list storage are included.

Use this instead for java count lines file code where input size is not guaranteed:

try (Stream<String> lines = Files.lines(path)) {
    return lines.count();
}

Memory comparison for a 1GB text file:

MethodMemory profileSafe for unknown size
Files.readAllLines()Can require several GBNo
Files.lines().count()Small, streamingYes
BufferedReaderSmall, streamingYes
BufferedInputStreamSmallestYes

Method 6: Apache Commons IO

Apache Commons IO is useful when your project already depends on it. The current Apache Commons IO release is 2.22.0, published April 2026, and it requires Java 8 or newer.

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.22.0</version>
</dependency>
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;

import java.io.File;
import java.io.IOException;

public static long countLinesCommonsIO(String filePath) throws IOException {
    File file = new File(filePath);
    long count = 0;

    try (LineIterator iterator = FileUtils.lineIterator(file, "UTF-8")) {
        while (iterator.hasNext()) {
            iterator.nextLine();
            count++;
        }
    }
    return count;
}

Do not assume a lineCount() helper exists in Commons IO. Use LineIterator for memory-safe iteration, or FileUtils.readLines() only for small files.

Benchmark: Which Method Is Fastest?

These benchmark numbers are directional results for a 5GB newline-delimited text file, OpenJDK 17, SSD storage, and a constrained -Xmx512m heap. They follow the same shape seen in public Java line-count benchmarks: byte scanning is fastest, stream and reader methods are close enough for normal work, and read-all methods do not belong on large files. Treat them as a starting point for java count lines large file testing in your own environment.

MethodAverage timePeak memoryRelative speed
BufferedInputStream byte scanabout 4.2sunder 1MBFastest
BufferedReader 64KB bufferabout 5.8sunder 10MBVery good
Files.lines().count()about 6.5sunder 10MBVery good
LineNumberReaderabout 6.8sunder 10MBGood
Files.lines().parallel().count()about 8.1sunder 20MBOften slower
Commons IO LineIteratorabout 7.2sunder 10MBGood
Files.readAllLines()OOM riskhugeDo not use

Decision summary:

  • Daily java 8 count lines code: Files.lines().count().
  • Java 7 compatibility: BufferedReader count lines.
  • Maximum speed: BufferedInputStream.
  • Existing Commons IO project: LineIterator.
  • Unknown file size: never Files.readAllLines().

Spring Boot Integration

Enterprise scenario

For spring boot count lines file workflows, put the counting logic in a service and keep controllers thin.

import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;

@Service
public class FileAnalysisService {

    public long countLines(Path filePath) throws IOException {
        try (Stream<String> lines = Files.lines(filePath, StandardCharsets.UTF_8)) {
            return lines.count();
        }
    }

    public long countLinesFromUpload(MultipartFile file) throws IOException {
        long count = 0;
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8))) {
            while (reader.readLine() != null) {
                count++;
            }
        }
        return count;
    }

    public long countLinesFromClasspath(String resourcePath) throws IOException {
        ClassPathResource resource = new ClassPathResource(resourcePath);
        long count = 0;
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8))) {
            while (reader.readLine() != null) {
                count++;
            }
        }
        return count;
    }
}

REST endpoint:

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Map;

@RestController
@RequestMapping("/api/files")
public class FileController {
    private final FileAnalysisService fileAnalysisService;

    public FileController(FileAnalysisService fileAnalysisService) {
        this.fileAnalysisService = fileAnalysisService;
    }

    @PostMapping("/line-count")
    public ResponseEntity<Map<String, Object>> countLines(@RequestParam("file") MultipartFile file) {
        try {
            long lineCount = fileAnalysisService.countLinesFromUpload(file);
            return ResponseEntity.ok(Map.of(
                "fileName", file.getOriginalFilename(),
                "lineCount", lineCount,
                "fileSize", file.getSize()
            ));
        } catch (IOException ex) {
            return ResponseEntity.internalServerError().body(Map.of("error", ex.getMessage()));
        }
    }
}

For Spring Boot 2.x on older Java versions, replace Map.of(...) with a mutable HashMap. The important spring boot count lines file rule is the same: keep file I/O in the service layer and keep the controller focused on HTTP concerns.

Handling Edge Cases

Empty files

All streaming methods above return 0 for an empty file. The byte-scanning method must explicitly track whether it saw any byte.

One line without a trailing newline

Reader-based methods return 1. The byte-scanning method must add one when the last byte is not '\n'.

Windows line endings

readLine() handles \r\n. Byte scanning counts '\n', so CRLF files still count correctly.

Non-empty lines

Java 11+:

try (Stream<String> lines = Files.lines(path)) {
    return lines.filter(line -> !line.isBlank()).count();
}

Java 8:

try (Stream<String> lines = Files.lines(path)) {
    return lines.filter(line -> !line.trim().isEmpty()).count();
}

Method timeline

Java 7              Java 8                  Java 11+              Java 17
|                   |                       |                      |
BufferedReader      Files.lines()           isBlank()              var in local code
LineNumberReader    Stream API              readString()           records elsewhere
BufferedInputStream try-with-resources      readAllLines still risky

Which Java Method Should You Use?

Your Java version?
|
+-- Java 7
|   +-- Use BufferedReader
|
+-- Java 8+
    |
    +-- Need simplest production code?
    |   +-- Files.lines().count()
    |
    +-- Need maximum throughput on huge files?
    |   +-- BufferedInputStream byte scan
    |
    +-- Existing Commons IO dependency?
    |   +-- LineIterator
    |
    +-- Small test fixture only?
        +-- Files.readAllLines()

FAQ

How do I count lines in a file in Java?

Use Files.lines(path).count() inside try-with-resources on Java 8+. Use BufferedReader if you need Java 7 compatibility. That is the safest starting point for "count lines in a file java" tasks.

For most teams, Files.lines java examples are short enough for documentation and safe enough for production.

What is the fastest way to count lines in Java?

BufferedInputStream byte scanning is usually fastest because it avoids creating one String per line.

How do I count lines in a large file in Java?

Use Files.lines(), BufferedReader, or BufferedInputStream. Do not use Files.readAllLines() on unknown or large files. For java count lines large file workloads, benchmark byte scanning first.

Does Files.lines() load the entire file into memory?

No. It is lazy, but the returned stream must be closed because it holds file resources.

Why can LineNumberReader.getLineNumber() return the wrong count?

It returns the current line number, not a precomputed total. If you call it before consuming the file, the result is not the final count.

How do I count non-empty lines in Java?

Use Files.lines(path).filter(line -> !line.isBlank()).count() on Java 11+, or !line.trim().isEmpty() on Java 8.

How do I count lines in a Java Spring Boot application?

Use a service method. For files on disk, use Files.lines(). For MultipartFile, wrap file.getInputStream() in BufferedReader. This is the practical spring boot count lines file pattern.

What is the difference between BufferedReader and LineNumberReader?

LineNumberReader extends BufferedReader and tracks current line number. It is useful for diagnostics, but it is not faster or simpler for total counts.

How do I count lines in a UTF-8 file in Java?

Pass StandardCharsets.UTF_8 explicitly to Files.lines() or InputStreamReader.

Sources Checked

Do Not Want to Write Java Code?

If you are processing a file outside your Java application, a log file, CSV export, or data dump, paste it into the Line Counter. No code, no JVM, no OutOfMemoryError.

Quick CTA

Need a line count without writing Java? Use the Line Counter tool and get the result in your browser.

Frequently Asked Questions

How do I count lines in a file in Java?

For Java 8+, use Files.lines(path).count() inside try-with-resources. For Java 7, use BufferedReader and increment a counter while readLine() returns non-null.

What is the fastest way to count lines in Java?

BufferedInputStream byte scanning is usually fastest because it counts newline bytes without creating String objects for every line.

How do I count lines in a large file in Java?

Avoid Files.readAllLines(). Use Files.lines(), BufferedReader, or BufferedInputStream. For very large files, BufferedInputStream gives the best throughput and lowest memory use.

Does Files.lines() load the entire file into memory?

No. Files.lines() returns a lazily populated stream, but the stream must be closed because it is backed by an open file.

Why can LineNumberReader give the wrong count?

LineNumberReader reports the current line number, not the total file size. You must read the whole file first, and it returns an int, which is also a limitation for extremely large files.

How do I count non-empty lines in Java?

Use Files.lines(path).filter(line -> !line.isBlank()).count() on Java 11+, or !line.trim().isEmpty() for Java 8.

How do I count lines in a Spring Boot application?

Put the counting logic in a service. For uploaded MultipartFile input, wrap file.getInputStream() with BufferedReader and count readLine() results.

How do I count lines in a UTF-8 file in Java?

Pass StandardCharsets.UTF_8 to Files.lines() or InputStreamReader. Do not rely on platform default encoding for production file processing.

Related Guides