Efficient Text Processing with Java BufferedReader

JavaJavaBeginner
Practice Now

Introduction

In this lab, we will be using the Java BufferedReader class, which is part of the java.io package. BufferedReader is used to read text from a character input stream and buffers the characters for better performance. The class wraps other reader classes and input streams, allowing us to improve the overall efficiency and performance of our programs. We will explore the different constructors, methods and use cases of BufferedReader in order to understand its functionality.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("`Java`")) -.-> java/ProgrammingTechniquesGroup(["`Programming Techniques`"]) java(("`Java`")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["`Object-Oriented and Advanced Concepts`"]) java(("`Java`")) -.-> java/FileandIOManagementGroup(["`File and I/O Management`"]) java(("`Java`")) -.-> java/BasicSyntaxGroup(["`Basic Syntax`"]) java(("`Java`")) -.-> java/StringManipulationGroup(["`String Manipulation`"]) java(("`Java`")) -.-> java/DataStructuresGroup(["`Data Structures`"]) java(("`Java`")) -.-> java/SystemandDataProcessingGroup(["`System and Data Processing`"]) java/ProgrammingTechniquesGroup -.-> java/scope("`Scope`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/classes_objects("`Classes/Objects`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/class_methods("`Class Methods`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/exceptions("`Exceptions`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/modifiers("`Modifiers`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/oop("`OOP`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/packages_api("`Packages / API`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/user_input("`User Input`") java/FileandIOManagementGroup -.-> java/files("`Files`") java/FileandIOManagementGroup -.-> java/read_files("`Read Files`") java/BasicSyntaxGroup -.-> java/identifier("`Identifier`") java/StringManipulationGroup -.-> java/stringbuffer_stringbuilder("`StringBuffer/StringBuilder`") java/DataStructuresGroup -.-> java/arrays("`Arrays`") java/BasicSyntaxGroup -.-> java/comments("`Comments`") java/BasicSyntaxGroup -.-> java/data_types("`Data Types`") java/BasicSyntaxGroup -.-> java/if_else("`If...Else`") java/BasicSyntaxGroup -.-> java/operators("`Operators`") java/BasicSyntaxGroup -.-> java/output("`Output`") java/StringManipulationGroup -.-> java/strings("`Strings`") java/BasicSyntaxGroup -.-> java/type_casting("`Type Casting`") java/BasicSyntaxGroup -.-> java/variables("`Variables`") java/BasicSyntaxGroup -.-> java/while_loop("`While Loop`") java/SystemandDataProcessingGroup -.-> java/string_methods("`String Methods`") java/SystemandDataProcessingGroup -.-> java/system_methods("`System Methods`") subgraph Lab Skills java/scope -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/classes_objects -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/class_methods -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/exceptions -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/modifiers -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/oop -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/packages_api -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/user_input -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/files -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/read_files -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/identifier -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/stringbuffer_stringbuilder -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/arrays -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/comments -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/data_types -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/if_else -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/operators -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/output -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/strings -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/type_casting -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/variables -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/while_loop -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/string_methods -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} java/system_methods -.-> lab-117473{{"`Efficient Text Processing with Java BufferedReader`"}} end

Create a BufferedReader with a FileReader

The BufferedReader constructor takes a Reader object as a parameter. We can create a reader using a FileReader, which reads text files in the default encoding. In this step, we will read a file with the BufferedReader class by wrapping a FileReader.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try {
            FileReader fileReader = new FileReader(path);
            BufferedReader bufferedReader = new BufferedReader(fileReader); //Creating a BufferedReader by wrapping the FileReader
            // Add code to read data from the file here

            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

To run the code, compile the file with javac BufferedReaderDemo.java, and then run it with java BufferedReaderDemo.

Use a BufferedReader with a Stream

We can also create a BufferedReader using an input stream as a source. In this step, we will wrap an InputStreamReader with BufferedReader and read data from System.in. This will read data that we enter using the keyboard.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        try {
            InputStreamReader isr = new InputStreamReader(System.in);
            BufferedReader bufferedReader = new BufferedReader(isr); //Creating a BufferedReader
            System.out.println("Enter Something:");
            String line = bufferedReader.readLine(); //Read input from console
            System.out.println("You Entered: " + line); //Print out the input

            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Closing the Stream

We should always use the close() method of the BufferedReader to release all the system resources associated with the reader. To simplify the code, we can use a try-with-resources block to automatically close the stream.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            // Add code to read data from the file here

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

BufferedReader Vs. Scanner

Both Scanner and BufferedReader can be used to read data from external sources. However, there are some differences between these two classes. In this step, we will compare some key differences.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader);
             Scanner scanner = new Scanner(fileReader)) {
            long startTime = System.nanoTime();
            // Reading file with BufferedReader
            bufferedReader.readLine();
            while (bufferedReader.readLine() != null) ;
            long endTime = System.nanoTime();
            System.out.println("Time taken by BufferedReader : " + (endTime - startTime) + "ns");

            startTime = System.nanoTime();
            // Reading file with Scanner
            scanner.nextLine();
            while (scanner.hasNextLine()) scanner.nextLine();
            endTime = System.nanoTime();
            System.out.println("Time taken by Scanner : " + (endTime - startTime) + "ns");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

This code compares the time taken by BufferedReader and Scanner to read data from the same file. The timings will vary, but the output will tell you which one took longer.

Reading Files Line by Line

The BufferedReader class provides several methods to read data. The readLine() method reads one line at a time. This method returns null if we reach the end of the stream. In this step, we will read a file using BufferedReader.readLine().

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            String line;
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println(line);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Reading Single Characters from a File

We can also read a single character at a time by using the read() method of the BufferedReader class. This method returns the char read as an integer. If we reach the end of the stream, then it returns -1.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            int charRead;
            while ((charRead = bufferedReader.read()) != -1) {
                System.out.print((char) charRead);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Reading Multiple Characters from a File

The read() method can read multiple characters at a time. We need to pass a char array in which it will store the data. We also need to use an offset that indicates the starting index of the char array. The stored data starts from this index. We also need to mention the maximum length of characters to read.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            char[] charArr = new char[5];
            bufferedReader.read(charArr, 0, 5);
            System.out.print(charArr);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Skipping Characters

The BufferedReader class provides a skip() method, which we can use to skip characters. It takes a long type parameter.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            int charRead;
            StringBuilder sb = new StringBuilder();
            while ((charRead = bufferedReader.read()) != -1) {
                if (charRead != '*') {
                    sb.append((char) charRead);
                } else {
                    bufferedReader.skip(1);
                }
            }
            System.out.println(sb);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Mark and Reset

The BufferedReader class provides us the mark() method to mark a specific character. We can come back to this marked character anytime in the future by using the reset() method. The mak() method takes an integer as input that denotes the maximum bytes that can be read before the mark becomes invalid.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            char[] charArr = new char[5];
            charArr[0] = (char) bufferedReader.read();
            charArr[1] = (char) bufferedReader.read();

            bufferedReader.mark(10);
            bufferedReader.skip(1);
            charArr[2] = (char) bufferedReader.read();
            charArr[3] = (char) bufferedReader.read();
            charArr[4] = (char) bufferedReader.read();
            System.out.println(charArr);

            bufferedReader.reset();
            char asterisk = (char) bufferedReader.read();
            System.out.print(asterisk);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Summary

In this lab, we used the Java BufferedReader class to read text from a character input stream. We learned how to wrap other reader classes and input streams with BufferedReader to improve performance and efficiency. We covered topics such as reading single and multiple characters from a file, skipping characters, marking and resetting positions in a file, and comparing BufferedReader and Scanner classes. We also used try-with-resources blocks to automatically close the stream and avoid memory leaks.

Other Java Tutorials you may like