← Back to Core Java Course | Chapter 12: File I/O | Lesson 1 of 9

Java I/O Streams

A stream represents a continuous flow of data into or out of a program, and every file-reading or file-writing operation in Java is ultimately built on top of an input or output stream.

What is a Stream?

A stream in Java represents a continuous flow of data, either coming into a program from a source like a file or network connection, or going out of a program to a destination, and every file operation is built on top of an input or output stream.

Example: What is a Stream?

java
import java.io.FileWriter;
import java.io.IOException;
public class Main {
	public static void main(String[] args) throws IOException {
		FileWriter writer = new FileWriter("data.txt"); // stream: flow of data out
		writer.write("Hello");
		writer.close();
		System.out.println("Written");
	}
}

Byte Streams vs Character Streams

Java splits streams into two families: byte streams like FileInputStream and FileOutputStream handle raw binary data one byte at a time, while character streams like FileReader and FileWriter handle text and automatically manage character encoding.

Example: Byte Streams vs Character Streams

java
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
public class Main {
	public static void main(String[] args) throws IOException {
		FileOutputStream byteStream = new FileOutputStream("bytes.dat"); // raw binary
		byteStream.write(65);
		byteStream.close();
		FileWriter charStream = new FileWriter("text.txt"); // text
		charStream.write("Hello");
		charStream.close();
	}
}

Input Streams and Output Streams

An InputStream provides data flowing into a program through methods like read(), which returns -1 once the end of the data is reached, while an OutputStream provides a write() method for sending data out to its destination.

Example: Input Streams and Output Streams

java
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
public class Main {
	public static void main(String[] args) throws IOException {
		FileWriter writer = new FileWriter("data.txt");
		writer.write("Hi");
		writer.close();
		FileReader reader = new FileReader("data.txt");
		int c;
		while ((c = reader.read()) != -1) { // -1 marks end of data
			System.out.print((char) c);
		}
		reader.close();
	}
}

Stream Buffering

Reading or writing one byte or character at a time is slow because each call can trigger a separate disk operation, so buffered streams like BufferedReader and BufferedWriter batch data in memory to reduce the number of actual I/O operations.

Example: Stream Buffering

java
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.IOException;
public class Main {
	public static void main(String[] args) throws IOException {
		BufferedWriter writer = new BufferedWriter(new FileWriter("data.txt")); // batches writes
		writer.write("Hello");
		writer.close();
		System.out.println("Written with buffering");
	}
}

Closing Streams Properly

Every stream must eventually be closed to release the underlying file handle or system resource, and Java's try-with-resources statement does this automatically and safely even when an exception interrupts the read or write.

Example: Closing Streams Properly

java
import java.io.FileWriter;
import java.io.IOException;
public class Main {
	public static void main(String[] args) throws IOException {
		try (FileWriter writer = new FileWriter("data.txt")) { // try-with-resources auto-closes
			writer.write("Hello");
		}
		System.out.println("Closed automatically");
	}
}

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.