Introduction
Input and output (I/O) is how a program communicates with the outside world — reading from the keyboard, writing to the screen, reading and writing files, sending data over the network. Java's I/O facilities are defined primarily in the java.io package, with higher-level non-blocking features added later in java.nio.
Streams
All Java I/O is built on the concept of a stream — a sequence of bytes or characters flowing from a source to a destination. Streams are one-way: a byte stream is either an InputStream (source) or an OutputStream (sink). Java provides two parallel hierarchies: byte streams for binary data (images, audio, class files) rooted at InputStream/OutputStream, and character streams for text data rooted at Reader/Writer. Character streams automatically handle character encoding (UTF-8, UTF-16, etc.) and are preferred for text.
Standard Streams
Three standard streams are always open when a Java program runs: System.in (keyboard), System.out (console), and System.err (error output). System.out.println() is the most-used I/O call in Java.
Reading from Keyboard
import java.io.*;
public class Echo {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter your name: ");
String name = br.readLine();
System.out.println("Hello, " + name);
}
}The modern alternative is java.util.Scanner, which wraps System.in and provides type-safe parsing methods such as nextInt(), nextDouble(), and nextLine().
File I/O with Byte Streams
try (FileInputStream in = new FileInputStream("input.bin");
FileOutputStream out = new FileOutputStream("output.bin")) {
int b;
while ((b = in.read()) != -1) out.write(b);
}The try-with-resources statement automatically closes the streams when the block exits, even if an exception is thrown.
File I/O with Character Streams
try (FileReader fr = new FileReader("text.txt");
BufferedReader br = new BufferedReader(fr);
FileWriter fw = new FileWriter("copy.txt");
BufferedWriter bw = new BufferedWriter(fw)) {
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
}Buffered Streams
BufferedReader and BufferedWriter wrap another reader/writer and add an internal buffer, dramatically improving performance for small reads. BufferedReader.readLine() returns an entire line at once. The analogous byte-stream classes are BufferedInputStream and BufferedOutputStream.
PrintWriter
PrintWriter provides println(), printf(), and format() methods for formatted output. Unlike System.out, it can be attached to any Writer — so you can write formatted text to a file just as easily as to the console.
try (PrintWriter pw = new PrintWriter(new FileWriter("report.txt"))) {
pw.printf("Average = %.2f%n", 87.345);
}File Class
The java.io.File class represents a file or directory in the filesystem. Useful methods include exists(), length(), isDirectory(), listFiles(), mkdirs(), delete(), and renameTo(). The newer java.nio.file.Path and Files classes (Java 7+) provide a more modern API.
Sequential vs Random Access
A FileInputStream reads bytes in sequence from start to finish. For random access — reading or writing any position in a file — use RandomAccessFile, which supports seek(position) and bidirectional reading and writing.
try (RandomAccessFile raf = new RandomAccessFile("data.bin", "rw")) {
raf.seek(100);
raf.writeInt(42);
raf.seek(100);
System.out.println(raf.readInt());
}Serialization
Java serialization converts an object graph into a byte stream that can be written to disk or sent over a network, then later reconstructed into an equivalent object. A class is serializable if it implements java.io.Serializable. Use ObjectOutputStream to write and ObjectInputStream to read.
Summary
Java I/O is built around streams: byte streams for binary data, character streams for text. Wrap base streams with buffered wrappers for performance, use try-with-resources for cleanup, and reach for RandomAccessFile or java.nio when the standard streams are not enough.
Important Questions
- Differentiate byte streams from character streams with examples.
- Write a Java program to read a file line by line using
BufferedReader. - Explain the purpose of
try-with-resources. - Compare
ScannerandBufferedReader. - What is
RandomAccessFile? When would you use it instead ofFileInputStream? - Write a program that copies a binary file using byte streams.
- Explain Java serialization with an example.
- List five useful methods of the
Fileclass.