Popular Searches
Popular Course Categories
Popular Courses

Working with BufferedReader and BufferedWriter

Working with BufferedReader and BufferedWriter

File Handling, I/O Streams, and Serialization

Working with BufferedReader and BufferedWriter in Java

Course: Core Java Training

Topic: Working with BufferedReader and BufferedWriter

Course Link: Core Java Training Course – JustAcademy

Demo Link: Register for a Course Demo

Website: JustAcademy Official Website


1. Introduction to BufferedReader and BufferedWriter

Java provides several classes for reading and writing data to files. BufferedReader and BufferedWriter are character-based input/output classes available in the java.io package. They use temporary memory buffers to make text processing more efficient.

BufferedReader reads characters from an input source, while BufferedWriter writes characters to an output destination. These classes are commonly used for text files, application logs, configuration files, reports, and data-processing applications.

  • BufferedReader: Reads text efficiently and supports line-by-line processing.
  • BufferedWriter: Writes text efficiently and supports convenient line separation.
  • Buffering: Stores data temporarily in memory to reduce frequent underlying I/O operations.
  • Resource management: Both classes should be closed after use, preferably with try-with-resources.

2. What Is BufferedReader?

BufferedReader is a Java class that reads text from a character input stream. It maintains a buffer of characters so that repeated read operations can often be served from memory rather than requiring a new underlying read each time.

It is commonly used with FileReader, InputStreamReader, or other Reader implementations.

Syntax

BufferedReader reader =
    new BufferedReader(new FileReader("input.txt"));

Here, FileReader opens the file and BufferedReader adds buffering to the character input.

Important Methods of BufferedReader

Method Description
read() Reads a single character and returns its integer value, or -1 at the end of the stream.
readLine() Reads a line of text without its line terminator and returns null at the end of the stream.
read(char[] cbuf) Reads characters into an array and returns the number of characters read, or -1 at the end.
ready() Indicates whether the stream is ready to be read without blocking.
skip(long n) Skips a specified number of characters, subject to the stream's behavior.
close() Closes the reader and its underlying resource.

3. What Is BufferedWriter?

BufferedWriter is a character-based output class that temporarily stores text in memory before sending it to an underlying Writer. It is commonly combined with FileWriter to write text files efficiently.

Syntax

BufferedWriter writer =
    new BufferedWriter(new FileWriter("output.txt"));

The writer collects character data in its buffer and sends it to the underlying writer as necessary, when flushed, or when closed.

Important Methods of BufferedWriter

Method Description
write(String str) Writes a string to the output stream.
write(int c) Writes a single character represented by an integer.
write(char[] cbuf) Writes characters from an array.
newLine() Writes the platform-specific line separator.
flush() Requests that buffered characters be sent to the underlying writer.
close() Flushes pending output and closes the writer.

4. Difference Between BufferedReader and BufferedWriter

Feature BufferedReader BufferedWriter
Purpose Reads character data. Writes character data.
Operation Input. Output.
Common method readLine() write()
Line handling Reads text line by line. Writes line separators using newLine().
Underlying class Can wrap FileReader or InputStreamReader. Can wrap FileWriter or OutputStreamWriter.
Typical use Reading logs, text files, and datasets. Writing reports, logs, and text files.

5. Reading a Text File Using BufferedReader

Reading a text file line by line is one of the most common uses of BufferedReader. The readLine() method simplifies this process.

Example 1: Read a File Line by Line

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

public class BufferedReaderExample {
    public static void main(String[] args) {
        try (
            BufferedReader reader =
                new BufferedReader(new FileReader("input.txt"))
        ) {
            String line;

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

        } catch (IOException e) {
            System.out.println("Error reading file: " + e.getMessage());
        }
    }
}

Explanation

  1. Import BufferedReader, FileReader, and IOException.
  2. Create a FileReader to open the input file.
  3. Wrap FileReader inside BufferedReader.
  4. Use readLine() to retrieve each line.
  5. Continue while the returned value is not null.
  6. Print each line to the console.
  7. Try-with-resources closes the reader automatically.

Sample input.txt

Welcome to Core Java.
BufferedReader simplifies text processing.
Java is useful for application development.

Output

Welcome to Core Java.
BufferedReader simplifies text processing.
Java is useful for application development.

6. Reading a File Character by Character

BufferedReader also supports the read() method. This method reads one character at a time and is useful when an application needs to examine individual characters.

Example 2: Read Characters Using BufferedReader

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

public class ReadCharacters {
    public static void main(String[] args) {
        try (
            BufferedReader reader =
                new BufferedReader(new FileReader("input.txt"))
        ) {
            int character;

            while ((character = reader.read()) != -1) {
                System.out.print((char) character);
            }

        } catch (IOException e) {
            System.out.println("Unable to read file: " + e.getMessage());
        }
    }
}

Explanation

  • The reader opens the file and buffers its character input.
  • The read() method returns the next character as an integer.
  • The integer is converted to a character before printing.
  • The loop stops when read() returns -1.

7. Writing Text to a File Using BufferedWriter

BufferedWriter is useful for creating text files and writing multiple lines of information. The write() method writes text, while newLine() adds a platform-appropriate line separator.

Example 3: Write Text to a File

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterExample {
    public static void main(String[] args) {
        try (
            BufferedWriter writer =
                new BufferedWriter(new FileWriter("output.txt"))
        ) {
            writer.write("Welcome to Java programming.");
            writer.newLine();
            writer.write("This file was created using BufferedWriter.");
            writer.newLine();
            writer.write("File handling is an important Java skill.");

            System.out.println("File written successfully.");

        } catch (IOException e) {
            System.out.println("Error writing file: " + e.getMessage());
        }
    }
}

Expected Content of output.txt

Welcome to Java programming.
This file was created using BufferedWriter.
File handling is an important Java skill.

Important: The default FileWriter constructor overwrites an existing file. Use append mode if existing content must be preserved.

8. Appending Data Using BufferedWriter

Appending means adding new content to the end of an existing file without deleting its previous contents. FileWriter supports append mode through its second constructor argument.

Syntax

BufferedWriter writer =
    new BufferedWriter(new FileWriter("output.txt", true));

The value true enables append mode.

Example 4: Append Text to a File

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class AppendTextExample {
    public static void main(String[] args) {
        try (
            BufferedWriter writer =
                new BufferedWriter(new FileWriter("output.txt", true))
        ) {
            writer.newLine();
            writer.write("This line has been appended to the file.");

            System.out.println("Text appended successfully.");

        } catch (IOException e) {
            System.out.println("Error appending text: " + e.getMessage());
        }
    }
}

Note: This example inserts a line separator before the new text. If the file is empty or already ends with a line separator, an extra blank line may result. Adjust the separator handling to match the application's requirements.

9. Reading and Writing a File Together

BufferedReader and BufferedWriter can be used together to read data from one file and write it to another. This approach is useful for copying text files and transforming text data.

Example 5: Copy Text from One File to Another

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

public class TextFileCopy {
    public static void main(String[] args) {
        try (
            BufferedReader reader =
                new BufferedReader(new FileReader("source.txt"));
            BufferedWriter writer =
                new BufferedWriter(new FileWriter("destination.txt"))
        ) {
            char[] buffer = new char[8192];
            int count;

            while ((count = reader.read(buffer)) != -1) {
                writer.write(buffer, 0, count);
            }

            System.out.println("Text file copied successfully.");

        } catch (IOException e) {
            System.out.println("Copy failed: " + e.getMessage());
        }
    }
}

How It Works

  1. Open the source file with BufferedReader.
  2. Open the destination file with BufferedWriter.
  3. Read characters into an array of 8192 characters.
  4. Write only the number of characters actually read.
  5. Repeat until the end of the source file.
  6. Close both resources automatically.

This approach preserves the sequence of decoded characters without reconstructing the file line by line. It does not guarantee byte-for-byte copying because decoding and encoding may change the original byte representation.

10. Reading and Writing UTF-8 Text

Character encoding determines how text is converted between characters and bytes. UTF-8 is widely used because it supports characters from many writing systems.

Using an explicit charset avoids relying on the JVM's default charset. Java's NIO file utilities provide convenient buffered readers and writers with a specified encoding.

Example 6: Read and Write UTF-8 Text

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

public class Utf8TextExample {
    public static void main(String[] args) {
        Path source = Path.of("source.txt");
        Path destination = Path.of("destination.txt");

        try (
            BufferedReader reader =
                Files.newBufferedReader(source, StandardCharsets.UTF_8);
            BufferedWriter writer =
                Files.newBufferedWriter(
                    destination, StandardCharsets.UTF_8
                )
        ) {
            char[] buffer = new char[8192];
            int count;

            while ((count = reader.read(buffer)) != -1) {
                writer.write(buffer, 0, count);
            }

            System.out.println("UTF-8 text processed successfully.");

        } catch (IOException e) {
            System.out.println("File operation failed: " + e.getMessage());
        }
    }
}

Compatibility: The example uses Path.of(), available in Java 11 and later. In older Java versions, use Paths.get().

11. Counting Lines in a Text File

BufferedReader is useful for processing large text files without loading every line into memory. A program can count lines by reading each line individually.

Example 7: Count the Number of Lines

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

public class LineCounter {
    public static void main(String[] args) {
        long lineCount = 0;

        try (
            BufferedReader reader =
                new BufferedReader(new FileReader("data.txt"))
        ) {
            while (reader.readLine() != null) {
                lineCount++;
            }

            System.out.println("Total lines: " + lineCount);

        } catch (IOException e) {
            System.out.println("Error processing file: " + e.getMessage());
        }
    }
}

Benefits

  • Processes the file sequentially.
  • Avoids storing all lines in a collection.
  • Works well for logs, reports, and text datasets.
  • Uses memory for the buffer and current line rather than the entire file.

12. Generating Reports Using BufferedWriter

BufferedWriter can generate structured reports containing headings, calculated values, and multiple lines of output.

Example 8: Generate a Student Report

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class StudentReport {
    public static void main(String[] args) {
        String name = "Rahul";
        int rollNumber = 101;
        double marks = 87.5;

        try (
            BufferedWriter writer =
                new BufferedWriter(new FileWriter("student-report.txt"))
        ) {
            writer.write("STUDENT REPORT");
            writer.newLine();
            writer.write("------------------------");
            writer.newLine();
            writer.write("Name: " + name);
            writer.newLine();
            writer.write("Roll Number: " + rollNumber);
            writer.newLine();
            writer.write("Marks: " + marks);
            writer.newLine();

            System.out.println("Student report created.");

        } catch (IOException e) {
            System.out.println("Unable to create report: " + e.getMessage());
        }
    }
}

Expected File Content

STUDENT REPORT
------------------------
Name: Rahul
Roll Number: 101
Marks: 87.5

13. Understanding Buffering and Performance

Buffering can improve file-processing performance by reducing frequent underlying I/O operations. However, it does not guarantee that every program will become faster. Performance depends on file size, storage speed, buffer size, encoding, and application logic.

Approach Potential Benefit Consideration
Reading one character at a time Useful for character-level logic. May involve many Java method calls.
Reading with readLine() Convenient for line-oriented processing. Very long lines may require significant memory.
Reading character chunks Useful for large text files. Requires tracking the number of characters read.
Writing with BufferedWriter Reduces frequent underlying write operations. Unnecessary frequent flush calls can reduce efficiency.
Using custom buffer sizes May improve throughput for certain workloads. Should be tested with realistic data.

14. Common Errors and Troubleshooting

Error or Problem Possible Cause Solution
FileNotFoundException The input file does not exist or its path is incorrect. Verify the file path and working directory.
IOException A file operation failed. Check file permissions, storage availability, and the exception message.
Existing content is removed FileWriter was opened in overwrite mode. Use append mode when existing content must be retained.
Unexpected characters appear Incompatible character encodings. Specify a consistent charset, such as UTF-8.
Output is incomplete The application did not finish writing or encountered an error. Use try-with-resources and handle exceptions properly.
High memory consumption The application stores the entire file or very long lines in memory. Process the file incrementally and avoid unnecessary collections.
Slow processing Inefficient logic or excessive flushing. Review the algorithm and benchmark realistic workloads.
Binary file becomes corrupted Binary content was decoded and rewritten as text. Use buffered byte streams for binary files.

15. Best Practices for BufferedReader and BufferedWriter

  • Use try-with-resources to close readers and writers automatically.
  • Use BufferedReader for character input and line-oriented processing.
  • Use BufferedWriter for efficient text output.
  • Choose byte streams for images, PDFs, audio, and other binary files.
  • Specify an explicit character encoding when interoperability matters.
  • Use append mode when you need to retain existing file content.
  • Avoid flushing after every small write unless immediate output is required.
  • Process large files incrementally instead of loading the entire contents into memory.
  • Handle IOException with meaningful error messages.
  • Test with empty files, large files, missing files, and non-English text.
  • Remember that BufferedReader and BufferedWriter do not automatically make file operations thread-safe.
  • Benchmark buffer sizes and processing strategies when performance is important.

16. Practice Exercises

  1. Create a text file and read its contents line by line using BufferedReader.
  2. Write your personal details to a text file using BufferedWriter.
  3. Append a new line to an existing file without deleting previous content.
  4. Copy a text file using a character array buffer.
  5. Count the lines in a large log file.
  6. Create a student report containing name, roll number, marks, and grade.
  7. Read and write UTF-8 text containing English and Hindi characters.
  8. Handle missing files and invalid paths using exception handling.
  9. Compare line-by-line processing with character-chunk processing.
  10. Create a program that copies only lines containing a specified keyword into another file.

17. Interview Questions and Answers

Q1. What is BufferedReader in Java?

Answer: BufferedReader is a character-based input class that buffers data and provides convenient methods for reading text, including readLine().

Q2. What is BufferedWriter in Java?

Answer: BufferedWriter is a character-based output class that buffers text before sending it to an underlying writer.

Q3. Which package contains BufferedReader and BufferedWriter?

Answer: Both classes belong to the java.io package.

Q4. What does readLine() return at the end of a file?

Answer: It returns null when no more lines are available.

Q5. What is the purpose of newLine()?

Answer: The newLine() method writes a line separator appropriate for the current platform.

Q6. Why use BufferedReader instead of FileReader alone?

Answer: BufferedReader adds buffering and provides convenient methods such as readLine(), simplifying text-processing tasks.

Q7. Can BufferedWriter append data to a file?

Answer: Yes. Wrap a FileWriter opened in append mode, such as new BufferedWriter(new FileWriter("file.txt", true)).

Q8. What is the difference between flush() and close()?

Answer: Flush requests that pending output be forwarded to the underlying writer. Close flushes pending output and releases the resource.

Q9. Can BufferedReader read binary files?

Answer: BufferedReader is intended for character data, not arbitrary binary data. Use byte-based streams for binary files.

Q10. How can large text files be processed efficiently?

Answer: Read lines or character chunks incrementally instead of loading the entire file into memory.

Q11. Why is UTF-8 useful?

Answer: UTF-8 supports a wide range of characters and is a common encoding for interoperable text files.

Q12. Does BufferedWriter guarantee that data is physically saved to disk after flush()?

Answer: No. Flush forwards buffered data to the underlying writer, but it does not guarantee physical storage-device durability.

18. Quick Revision Checklist

  • BufferedReader reads character data efficiently.
  • BufferedWriter writes character data efficiently.
  • readLine() reads a line and returns null at the end of the stream.
  • newLine() writes a platform-specific line separator.
  • FileWriter overwrites existing content by default.
  • Use append mode to preserve existing content.
  • Try-with-resources automatically closes resources.
  • Specify UTF-8 when predictable character encoding is required.
  • Use byte streams for binary files.
  • Process large files incrementally.
  • Avoid unnecessary flushing and measure performance when needed.

19. Conclusion

BufferedReader and BufferedWriter are essential Java classes for efficient text file processing. BufferedReader simplifies reading text and supports line-by-line operations, while BufferedWriter makes writing text convenient and efficient. When combined with appropriate file handling, character encoding, exception handling, and try-with-resources, these classes help developers create reliable Java applications.

Practice the examples by reading existing files, creating reports, appending data, copying text, and processing large datasets. These skills provide a strong foundation for advanced Java I/O, file management, and application development.


Learn Core Java with JustAcademy

Strengthen your programming fundamentals and explore Java file handling, streams, exception handling, and other important Core Java concepts.

Explore Core Java Training

Register for a Course Demo

Visit JustAcademy Official Website

Previous Next
whatsapp