Java I/O Streams: The River of Data ๐
Imagine youโre playing with a garden hose. Water flows through itโsometimes fast, sometimes slow. You can connect different hose parts to do different things: spray, drip, or even filter the water.
Java I/O Streams work exactly like that! Data (like water) flows through streams. Different stream types help you move different kinds of data.
๐ฏ The Big Picture
graph TD A["Your Program"] -->|Write| B["Output Stream"] B --> C["File/Network/Screen"] D["File/Network/Keyboard"] --> E["Input Stream"] E -->|Read| A
Two directions:
- Input Stream = Data coming INTO your program (like reading a book)
- Output Stream = Data going OUT of your program (like writing a letter)
1. Byte Streams: The Tiny Messengers ๐ฆ
What Are They?
Think of bytes as tiny LEGO blocks. Every file, every picture, every song is made of these tiny blocks.
Byte Streams move data one tiny block at a time.
The Two Main Characters
| Class | Job |
|---|---|
FileInputStream |
Reads bytes FROM a file |
FileOutputStream |
Writes bytes TO a file |
Real Example: Copy a Photo
// Read from one file
FileInputStream in =
new FileInputStream("cat.jpg");
// Write to another file
FileOutputStream out =
new FileOutputStream("cat_copy.jpg");
int oneByte;
// Read one byte at a time
while ((oneByte = in.read()) != -1) {
out.write(oneByte);
}
in.close();
out.close();
Whatโs happening?
- Open the photo file
- Read one tiny piece
- Write that piece to new file
- Repeat until done!
When to Use Byte Streams?
โ Images, videos, music files โ Any binary (non-text) data โ When you need exact byte-for-byte copy
2. Character Streams: The Letter Writers โ๏ธ
What Are They?
Bytes are great, but text is special. Letters like โAโ, โใใใซใกใฏโ, or โ๐โ need special care.
Character Streams understand letters and symbols from ANY language!
The Two Main Characters
| Class | Job |
|---|---|
FileReader |
Reads characters FROM a file |
FileWriter |
Writes characters TO a file |
Real Example: Read a Story
FileReader reader =
new FileReader("story.txt");
int oneChar;
while ((oneChar = reader.read()) != -1) {
// Convert number to character
System.out.print((char) oneChar);
}
reader.close();
Real Example: Write a Note
FileWriter writer =
new FileWriter("note.txt");
writer.write("Hello, World!");
writer.write("\n"); // New line
writer.write("Java is fun!");
writer.close();
Byte vs Character: Quick Compare
graph TD A["Raw Data"] --> B{What type?} B -->|Text/Letters| C["Character Stream"] B -->|Images/Audio| D["Byte Stream"] C --> E["FileReader/FileWriter"] D --> F["FileInputStream/FileOutputStream"]
3. Buffered Streams: The Smart Helpers ๐
The Problem
Imagine going to the grocery store. Would you:
- Make 100 trips, carrying ONE item each time? ๐ฉ
- Make 1 trip with a shopping cart holding 100 items? ๐
Reading one byte at a time is SLOW (like 100 trips).
The Solution: Buffers!
A buffer is like a shopping cart. It collects many bytes/characters, then moves them all at once!
The Magic Wrapper
// SLOW: One byte at a time
FileInputStream slow =
new FileInputStream("big.txt");
// FAST: Many bytes at once!
BufferedInputStream fast =
new BufferedInputStream(slow);
All Four Buffered Types
| Buffered Class | Wraps | For |
|---|---|---|
BufferedInputStream |
FileInputStream | Fast byte reading |
BufferedOutputStream |
FileOutputStream | Fast byte writing |
BufferedReader |
FileReader | Fast text reading |
BufferedWriter |
FileWriter | Fast text writing |
Super Power: Read Lines!
BufferedReader reader =
new BufferedReader(
new FileReader("poem.txt"));
String line;
// Read whole lines at once!
while ((line = reader.readLine())
!= null) {
System.out.println(line);
}
reader.close();
.readLine() reads an entire line! No more character-by-character!
Writing Lines Too
BufferedWriter writer =
new BufferedWriter(
new FileWriter("diary.txt"));
writer.write("Day 1: Learned Java!");
writer.newLine(); // Add line break
writer.write("Day 2: Mastered Streams!");
writer.close();
4. Data Streams: The Type Experts ๐ข
The Challenge
What if you want to save a number like 42 or 3.14?
With regular streams:
42becomes โ4โ and โ2โ (two characters)- Thatโs messy and wasteful!
Data Streams Save the Day!
They understand Java types: int, double, boolean, String!
The Dynamic Duo
| Class | Job |
|---|---|
DataInputStream |
Reads Java types |
DataOutputStream |
Writes Java types |
Save a Playerโs Score
DataOutputStream out =
new DataOutputStream(
new FileOutputStream("save.dat"));
// Save different types!
out.writeUTF("Player1"); // String
out.writeInt(9500); // int
out.writeDouble(3.14); // double
out.writeBoolean(true); // boolean
out.close();
Load the Score Back
DataInputStream in =
new DataInputStream(
new FileInputStream("save.dat"));
// Read in SAME ORDER you wrote!
String name = in.readUTF();
int score = in.readInt();
double level = in.readDouble();
boolean alive = in.readBoolean();
in.close();
โ ๏ธ Golden Rule
Read in the SAME ORDER you wrote!
If you wrote: String โ int โ double You must read: String โ int โ double
5. Object Streams: The Magic Teleporter ๐ช
The Ultimate Power
What if you could save an entire objectโwith all its dataโto a file? Then load it back later, exactly as it was?
Thatโs Object Streams! Itโs like teleporting a toy into a box, then bringing it back to life later.
Making Objects Teleport-Ready
Your class needs a special permission slip:
import java.io.Serializable;
class Player implements Serializable {
String name;
int score;
Player(String n, int s) {
name = n;
score = s;
}
}
Just add implements Serializable. Thatโs it!
Save an Object
Player hero = new Player("Alex", 9999);
ObjectOutputStream out =
new ObjectOutputStream(
new FileOutputStream("hero.dat"));
out.writeObject(hero); // Teleport!
out.close();
Load the Object Back
ObjectInputStream in =
new ObjectInputStream(
new FileInputStream("hero.dat"));
// Bring it back to life!
Player loaded = (Player) in.readObject();
System.out.println(loaded.name); // Alex
System.out.println(loaded.score); // 9999
in.close();
The Full Picture
graph TD A["Java Object"] -->|writeObject| B["ObjectOutputStream"] B --> C["File on Disk"] C --> D["ObjectInputStream"] D -->|readObject| E["Java Object Restored!"]
๐ Stream Family Tree
graph LR A["All Streams"] --> B["Byte Streams"] A --> C["Character Streams"] B --> D["FileInputStream"] B --> E["FileOutputStream"] B --> F["BufferedInputStream"] B --> G["BufferedOutputStream"] B --> H["DataInputStream"] B --> I["DataOutputStream"] B --> J["ObjectInputStream"] B --> K["ObjectOutputStream"] C --> L["FileReader"] C --> M["FileWriter"] C --> N["BufferedReader"] C --> O["BufferedWriter"]
๐ Quick Summary
| Stream Type | Best For | Key Classes |
|---|---|---|
| Byte | Images, audio, any raw data | FileInputStream, FileOutputStream |
| Character | Text files, readable content | FileReader, FileWriter |
| Buffered | Speed boost for any stream | BufferedReader, BufferedWriter |
| Data | Save Java primitives (int, double) | DataInputStream, DataOutputStream |
| Object | Save entire Java objects | ObjectInputStream, ObjectOutputStream |
๐ก Remember This!
- Byte Streams = Raw data (like moving boxes)
- Character Streams = Text data (like reading books)
- Buffered Streams = Shopping cart (faster!)
- Data Streams = Type-aware (knows int, double, etc.)
- Object Streams = Magic teleporter (save whole objects!)
Always close your streams! Like turning off a faucet. ๐ฐ
// Modern way: try-with-resources
try (FileReader r = new FileReader("f.txt")) {
// Use the stream
} // Auto-closed! No leak!
๐ You Did It!
You now understand how Java moves data around! Whether itโs a tiny text file or a complex game save, you know which stream to pick.
The river of data is yours to command! ๐
