# How to read a file line by line in Java

By Atta Ur Rehman Shah (https://attacomsian.com/about). Published Aug 24, 2019, updated Feb 18, 2020. Topics: Java.
Canonical URL: https://attacomsian.com/blog/how-to-read-a-file-line-by-line-in-java

> Learn about seven different ways to read a file line-by-line in Java (Scanner, BufferedReader, Java 8 Streams, New I/O API, RandomAccessFile, Apache Commons IO, & Okie).

Sometimes we want to read a file line by line to a string to process the content. A good example is [reading a CSV file line by line](https://attacomsian.com/blog/read-write-csv-files-core-java) and then splitting the line by comma (`,`) into multiple columns.

In Java, there are various options available to choose from when you need to read a file line by line.

## 1. Scanner

The `Scanner` class presents the simplest way to read a file line by line in Java. We can use [Scanner](https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html) class to open a file and then read its content line by line.

A Scanner breaks its input into tokens using a delimiter pattern, which is a new line in our case:

```java
try {
    // open file to read
    Scanner scanner = new Scanner(new File("examplefile.txt"));

    // read until end of file (EOF)
    while (scanner.hasNextLine()) {
        System.out.println(scanner.nextLine());
    }

    // close the scanner
    scanner.close();
        
} catch (FileNotFoundException ex) {
    ex.printStackTrace();
}
```

The `hasNextLine()` method returns `true` if there is another line in the input of this scanner without advancing the file read position. 

To read data and move on to the next line, we should use the `nextLine()` method. This method moves the scanner past the current line and returns the rest of the current line, excluding any line separator at the end. The read position is then set to the beginning of the next line.

Since the `nextLine()` method continues to search through the input looking for a line separator, it may buffer all of the input searching for the line to skip if no line separators are present.

## 2. BufferedReader

The [BufferedReader](https://docs.oracle.com/javase/8/docs/api/java/io/BufferedReader.html) class provides an efficient way to read characters, arrays, and lines from a character-input stream.

As the name suggests, it buffers the characters up to 8MB (or 8192KB) which is large enough for most use cases. If the file you are reading is larger than the default buffer size, you can customize the default size:

```java
BufferedReader br = new BufferedReader(new FileReader("foo.txt"), size);
```

The `BufferedReader` constructor accepts a `Reader` instance (like `FileReader`, `InputStreamReader`) as character-input stream source. Here is a simple example that shows how to use it for reading a file line by line:

```java
try {
    // create a reader instance
    BufferedReader br = new BufferedReader(new FileReader("examplefile.txt"));

    // read until end of file
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }

    // close the reader
    br.close();
        
} catch (IOException ex) {
    ex.printStackTrace();
}
```

The `readLine()` method reads a line of text from the file and returns a string containing the contents of the line, excluding any line-termination characters or null.

> **Note:** A `null` value does not mean that the string is empty. Rather it shows that the end of the file is reached.

Alternatively, you can use `lines()` method from `BufferedReader` class that returns a `Stream` of lines. You can easily convert this stream into a list or read the lines like the following:

```java
try {
    // create a reader instance
    BufferedReader br = new BufferedReader(new FileReader("examplefile.txt"));

    // list of lines
    List<String> list = new ArrayList<>();

    // convert stream into list
    list = br.lines().collect(Collectors.toList());

    // print all lines
    list.forEach(System.out::println);

    // close the reader
    br.close();
        
} catch (IOException ex) {
    ex.printStackTrace();
}
```

## 3. Java 8 Stream

Java 8 [Stream](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html) is another way (albeit cleaner) of reading a file line by line. We can use `Files.lines()` static method to initialize a lines stream like below:

```java
try {
    // initialize lines stream
    Stream<String> stream = Files.lines(Paths.get("examplefile.txt"));

    // read lines
    stream.forEach(System.out::println);

    // close the stream
    stream.close();

} catch (IOException ex) {
    ex.printStackTrace();
}
```

In addition to simple API, **streams are very useful for filtering, sorting and processing the data**. Let us extend the above example and filter out the lines that end with a colon (`:`), then sort them alphabetically, and convert to uppercase:

```java
try {
    // initialize lines stream
    Stream<String> stream = Files.lines(Paths.get("examplefile.txt"));

    // apply filter & sorting
    stream.filter(l -> l.endsWith(":"))
            .sorted()
            .map(String::toUpperCase)
            .forEach(System.out::println);
 
    // close the stream
    stream.close();
 
} catch (IOException ex) {
    ex.printStackTrace();
}
```

## 4. New I/O API

Java New I/O API or NIO (classes in `java.nio.*` package) provides the `Files.readAllLines()` method to read a text file line by line into a `List<String>`, as shown below:

```java
try {
    // read all lines
    List<String> lines = Files.readAllLines(Paths.get("examplefile.txt"));

    // print all lines
    lines.forEach(System.out::println);

} catch (IOException ex) {
    ex.printStackTrace();
}
```

## 5. RandomAccessFile

The [RandomAccessFile](https://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html) class provides a non-blocking mode of reading and writing files. A random-access file behaves like a large array of bytes stored in the file system.

We can use `RandomAccessFile` to open a file in reading mode and then use its `readLine()` method to read line by line:

```java
try {
    // open file in read mode
    RandomAccessFile file = new RandomAccessFile("examplefile.txt", "r");
    // read until end of file
    String line;
    while ((line = file.readLine()) != null) {
        System.out.println(line);
    }

    // close the file
    file.close();
        
} catch (IOException ex) {
    ex.printStackTrace();
}
```

## 6. Apache Commons IO

The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, and much more. Add the following to your `build.gradle` file to import the library in your project:

```groovy
implementation 'commons-io:commons-io:2.6'
```

If you are using Maven, add the following to your `pom.xml` file:

```xml
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
```

We can now use `FileUtils.readLines()` the static method from Apache Commons IO that reads all lines from a file into a `List<String>`:

```java
try {
    // read all lines of a file
    List<String> lines = FileUtils.readLines(Paths.get("examplefile.txt").toFile(), "UTF-8");

    // process the lines
    for (String line : lines) {
        System.out.println(line);
    }

} catch (IOException ex) {
    ex.printStackTrace();
}
```

Since Apache Commons IO reads all lines from the file at once, it may not be a good solution for reading large files. It will continue blocking the for loop execution in the above case until all lines are added to the `lines` object.

## 7. Okie

[Okie](https://github.com/square/okio) is another open-source I/O library developed by Square for Android, Kotlin, and Java. It complements native `java.io` and `java.nio` packages to make it much easier to access, save, and process the data.

To import Okie in your project, add the following to the `build.gradle` file:

```java
implementation 'com.squareup.okio:okio:2.4.0'
```

If you are using Maven, add the following to your `pom.xml` file:

```xml
<dependency>
    <groupId>com.squareup.okio</groupId>
    <artifactId>okio</artifactId>
    <version>2.4.0</version>
</dependency>
```

Now we can use `Okio.source()` method to open a source stream to read a file. The returned `Source` interface is very small and has limited uses. Okie provides `BufferedSource` class to wrap the source with a buffer that makes your program run faster.

Let us have an example:

```java
try {
    // open a source stream
    Source source = Okio.source(Paths.get("examplefile.txt").toFile());

    // wrap stream with a buffer
    BufferedSource bs = Okio.buffer(source);

    // read until end of file
    String line;
    while ((line = bs.readUtf8Line()) != null) {
        System.out.println(line);
    }

    // close the stream
    source.close();

} catch (IOException ex) {
    ex.printStackTrace();
}
```

The `readUtf8Line()` method reads the data until the next line delimiter – either `\n`, `\r\n`, or the end of the file. It returns that data as a string, omitting the delimiter at the end. When it encounters empty lines, the method will return an empty string. If there isn't no more data to read, it will return `null`.

## Further Reading

You may be interested in other Java I/O articles:

* [Reading and Writing Files in Java](https://attacomsian.com/blog/java-read-write-files)
* [How to Read and Write Text Files in Java](https://attacomsian.com/blog/java-read-write-text-files)
* [How to Read and Write Binary Files in Java](https://attacomsian.com/blog/java-read-write-binary-files)
* [Reading and Writing Files using Java NIO API](https://attacomsian.com/blog/java-read-write-files-nio-api)
