Java Core: File I/O and Serialization - BufferedReader & BufferedWriter
This document outlines the use of BufferedReader and BufferedWriter in Java for efficient file I/O. These classes are built on top of the base Reader and Writer classes and provide buffering, significantly improving performance, especially when dealing with character-based file operations.
1. Introduction
Directly reading and writing characters to a file using FileReader and FileWriter can be slow because each read/write operation interacts directly with the underlying operating system. BufferedReader and BufferedWriter address this by reading/writing data in larger chunks (buffers) to reduce the number of system calls.
Key Benefits:
- Performance: Reduced system calls lead to faster I/O operations.
- Convenience: Provide methods like
readLine()andnewLine()for easier handling of text files. - Character Encoding: Work with character streams, allowing for proper handling of different character encodings.
2. BufferedReader
BufferedReader reads text from a character-input stream, buffering characters to provide efficient reading of characters, arrays, and lines.
Key Methods:
BufferedReader(Reader in): Constructor. Takes aReaderobject (e.g.,FileReader) as input.int read(): Reads a single character. Returns the character as an integer, or -1 if the end of the stream is reached.int read(char[] cbuf): Reads characters into a character array. Returns the number of characters read, or -1 if the end of the stream is reached.String readLine(): Reads a line of text. Returns the line as aString, ornullif the end of the stream is reached. A line is terminated by any of\r,\n, or\r\n.void close(): Closes the reader, releasing system resources. Important to always close the reader!long skip(long n): Skipsncharacters in the input stream.
Example:
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.err.println("Error reading file: " + e.getMessage());
}
}
}
Explanation:
try-with-resources: This ensures that theBufferedReaderis automatically closed, even if exceptions occur. This is the recommended way to handle resources like readers and writers.new BufferedReader(new FileReader("input.txt")): Creates aBufferedReaderthat reads from aFileReaderassociated with the file "input.txt".reader.readLine(): Reads a line of text from the file.while ((line = reader.readLine()) != null): Continues reading lines until the end of the file is reached (whenreadLine()returnsnull).System.out.println(line): Prints each line to the console.catch (IOException e): Handles potential I/O exceptions.
3. BufferedWriter
BufferedWriter writes text to a character-output stream, buffering characters to provide efficient writing of characters, arrays, and strings.
Key Methods:
BufferedWriter(Writer out): Constructor. Takes aWriterobject (e.g.,FileWriter) as input.void write(int c): Writes a single character.void write(char[] cbuf): Writes a character array.void write(char[] cbuf, int off, int len): Writes a portion of a character array.void write(String s): Writes a string.void write(String s, int off, int len): Writes a portion of a string.void newLine(): Writes a line separator (platform-specific). Equivalent toSystem.lineSeparator().void flush(): Flushes the buffer, forcing any remaining data to be written to the underlying stream. Important to callflush()before closing the writer if you haven't already written everything.void close(): Closes the writer, releasing system resources. Important to always close the writer!
Example:
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("This is the first line.");
writer.newLine();
writer.write("This is the second line.");
writer.newLine();
writer.write("This is the third line.");
writer.flush(); // Optional, but good practice
} catch (IOException e) {
System.err.println("Error writing to file: " + e.getMessage());
}
}
}
Explanation:
try-with-resources: Ensures theBufferedWriteris automatically closed.new BufferedWriter(new FileWriter("output.txt")): Creates aBufferedWriterthat writes to aFileWriterassociated with the file "output.txt".writer.write(...): Writes strings and characters to the file.writer.newLine(): Writes a platform-specific line separator.writer.flush(): Forces any remaining data in the buffer to be written to the file. Whileclose()implicitly flushes, it's good practice to explicitly flush if you're not immediately closing the writer.catch (IOException e): Handles potential I/O exceptions.
4. Combining BufferedReader and BufferedWriter
You can combine BufferedReader and BufferedWriter to efficiently copy data 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 FileCopyExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"));
BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
System.err.println("Error copying file: " + e.getMessage());
}
}
}
5. Important Considerations
- Error Handling: Always wrap file I/O operations in
try-catchblocks to handle potentialIOExceptions. - Resource Management: Use
try-with-resourcesto ensure that readers and writers are automatically closed, preventing resource leaks. - Character Encoding: Be mindful of character encoding when working with text files. You can specify the encoding when creating
FileReaderandFileWriter(e.g.,new FileReader("file.txt", "UTF-8")). - Buffering Size: You can specify the buffer size when creating
BufferedReaderandBufferedWriter(e.g.,new BufferedReader(new FileReader("file.txt"), 8192)). The default size is usually sufficient, but you might experiment with larger sizes for very large files. flush()vs.close():flush()forces the buffer to be written to the underlying stream.close()flushes the buffer and closes the stream, releasing system resources. Always callclose()when you're finished with a reader or writer.
This comprehensive overview should provide a solid understanding of how to effectively use BufferedReader and BufferedWriter for file I/O in Java. Remember to prioritize error handling and resource management for robust and reliable code.