Table of Contents
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.
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
| Method | Java | Large files | Best use |
|---|---|---|---|
Files.lines().count() | 8+ | Safe | Modern default |
BufferedReader | 7+ | Safe | Legacy compatibility |
LineNumberReader | 7+ | Safe | Current line tracking |
BufferedInputStream | 7+ | Fastest | Huge files |
Files.readAllLines() | 7+ | Dangerous | Tiny files only |
| Apache Commons IO | dependency | Safe | Existing 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, notlong. - 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:
| Method | Memory profile | Safe for unknown size |
|---|---|---|
Files.readAllLines() | Can require several GB | No |
Files.lines().count() | Small, streaming | Yes |
BufferedReader | Small, streaming | Yes |
BufferedInputStream | Smallest | Yes |
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.
| Method | Average time | Peak memory | Relative speed |
|---|---|---|---|
BufferedInputStream byte scan | about 4.2s | under 1MB | Fastest |
BufferedReader 64KB buffer | about 5.8s | under 10MB | Very good |
Files.lines().count() | about 6.5s | under 10MB | Very good |
LineNumberReader | about 6.8s | under 10MB | Good |
Files.lines().parallel().count() | about 8.1s | under 20MB | Often slower |
Commons IO LineIterator | about 7.2s | under 10MB | Good |
Files.readAllLines() | OOM risk | huge | Do 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
- Oracle Java Stream documentation on closing I/O-backed streams: https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
- Oracle Java
Files.linesdocumentation: https://docs.oracle.com/javase/9/docs/api/java/nio/file/Files.html - Oracle Java
LineNumberReaderdocumentation: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/LineNumberReader.html - Apache Commons IO 2.22.0 overview: https://commons.apache.org/io/
Related Guides and Tools
- Python line counting for scripting and data files.
- Bash wc -l command for shell workflows.
- Node.js line counting for JavaScript servers and browser uploads.
- Go line counting for
bufio.Scanner, manual byte scanning, and concurrent log processing. - Rust line counting for
BufReader, zero-allocation byte scans, and Rayon. - C# line counting for
File.ReadLines,StreamReader, async I/O, and overflow-safe counts. - PHP line counting for
file(),fgets,SplFileObject, and WordPress uploads. - Ruby line counting for
File.foreach, encoding-safe counting, Rails uploads, and shell-safewc -l. - Kotlin line counting for
useLines,lineSequence, coroutines, Android URIs, and theSequencelifetime trap. - Haskell line counting for
readFile, lazy I/O handle pitfalls, and ByteString newline counting. - C line counting for
fread,mmap,wc -linternals, and cross-platform file-scanning tradeoffs. - Lua line counting for
io.lines, explicitio.open, LuaJIT-style embedded runtimes, and byte-scanning counters. - Scala line counting for
Source,Using,Files.lines, Spark, and the lazy iterator resource trap. - R line counting for
readLines(),readr::read_lines(), Unixwc -l, and theincomplete final linewarning. - Perl line counting for
$.,IO::File,sysread, and multi-file line-number reset pitfalls. - SQL row counting for
COUNT(*), database estimates, and ORM count APIs. - cross-platform line counting for Linux, macOS, and Windows commands.
- Line Counter tool for no-code file counting.
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
20 min read
How to Count Lines in Python: 7 Methods, Benchmarked and Battle-Tested
Count lines in Python strings, text files, large files, and directories. Includes real performance benchmarks, empty file handling, splitlines vs split, and production-ready functions.
14 min read
How to Count Lines in a File in Haskell (And Why `lines ""` Is Not the Real Trap)
Count lines in a file in Haskell — readFile, lines, Data.ByteString, and strict vs lazy IO. Covers the `lines ""` myth, final-newline off-by-one bugs, Lazy IO file descriptor leaks, and high-performance streaming with ByteString.
13 min read
How to Count Lines in a File in C (And Why `fgetc` Is 9x Slower Than `fread`)
Count lines in a file in C — fgets, fread, mmap, and the large performance gap between them. Covers `wc -l` internals, Windows vs Linux portability, long-line traps, and production-ready counting patterns for large files.
14 min read
How to Count Lines in a File Using Kotlin (And the useLines Sequence Trap Nobody Documents)
Count lines in a file using Kotlin — File.readLines, useLines, BufferedReader, and Coroutines Flow. Covers the useLines Sequence escape trap, OOM risks, and Android/Spring Boot patterns with benchmarks.