Object Oriented Programming With JavaUnit 713 min read
File Handling & I/O in Java: Streams, Files, and Exceptions
Unit 7 of Object Oriented Programming With Java covers file I/O operations in Java, including file handling techniques, stream classes (FileInputStream, FileOutputStream, BufferedReader, etc.), exception handling for I/O errors, and practical applications like reading/writing text and binary data. This note explains co
Key Concepts and Definitions
1. File Handling in Java
File handling refers to the process of reading from and writing to files using Java’s built-in classes. Files can store data permanently, unlike variables that exist only during program execution.
2. Streams in Java
Streams are sequences of data used to read from or write to files, networks, or other sources. Java provides two types of streams:
- Byte Streams: Handle raw bytes (e.g.,
FileInputStream,FileOutputStream). - Character Streams: Handle characters (e.g.,
FileReader,FileWriter,BufferedReader,BufferedWriter).
3. File Class
The java.io.File class represents file and directory pathnames. It provides methods to create, delete, and check file properties (e.g., exists(), createNewFile()).
4. Exception Handling for I/O
I/O operations often throw exceptions (e.g., FileNotFoundException, IOException). These must be handled using try-catch blocks or declared with throws.
In the Real World
eSewa and Khalti (Nepal)
- These apps use file handling to store transaction records (e.g., payment receipts, user profiles) in databases or log files. For example, when you pay a bill via eSewa, the transaction details are written to a file (or database) for record-keeping and future reference.
- Idea Used: Writing data to files (
FileOutputStreamorBufferedWriter) to log transactions securely.
Daraz (Nepal/E-commerce)
- Daraz’s order management system uses file handling to track orders, inventory, and user data. For instance, when you place an order, the system writes order details (product ID, quantity, customer info) to a file or database for processing.
- Idea Used: Reading/writing structured data (e.g., CSV or JSON files) to manage orders efficiently.
NTC (Nepal Telecommunications)
- NTC’s billing system generates monthly bills for customers. These bills are often stored as files (e.g., PDF or text files) and sent to users via email or printed. The system reads customer data from files to calculate bills.
- Idea Used: Reading customer data from files (
FileReader) and writing bills to files (FileWriter).
Visualizing File Handling
1. File Structure and Paths
classDiagram
class File {
+String name
+String path
+boolean exists()
+boolean createNewFile()
+boolean delete()
}
class FileInputStream {
+read(byte[] b) int
}
class FileOutputStream {
+write(byte[] b) void
}
File --> FileInputStream : "Reads from"
File --> FileOutputStream : "Writes to"2. Stream Hierarchy
java.io.InputStream
│
├── FileInputStream (byte stream)
│ └── BufferedInputStream (buffered)
│
└── Reader (character stream)
├── FileReader
│ └── BufferedReader
└── InputStreamReader
Step-by-Step: Writing to a File
Example: Saving Movie Objects to a File
Task: Create a Movie class and write objects to Comedy.dat if the genre is "comedy."
Code Example
import java.io.*;
class Movie {
int id;
String genre;
public Movie(int id, String genre) {
this.id = id;
this.genre = genre;
}
}
public class WriteMovieToFile {
public static void main(String[] args) {
Movie movie = new Movie(1, "comedy");
try (FileOutputStream fos = new FileOutputStream("Comedy.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(movie);
System.out.println("Movie saved to Comedy.dat");
} catch (IOException e) {
e.printStackTrace();
}
}
}
State After Writing
graph LR
A["File: Comedy.dat (before writing)"] -->|"Empty"| B["File: Comedy.dat (after writing)"]
B --> C["Binary data:\nMovie(id=1, genre=comedy)"]Trace Table
| Step | Action | File State | Exception |
|---|---|---|---|
| 1 | Create FileOutputStream |
Opened for writing | None |
| 2 | Create ObjectOutputStream |
Ready to write objects | None |
| 3 | oos.writeObject(movie) |
Binary data written | None |
| 4 | Close streams | File closed | None |
Step-by-Step: Reading from a File
Example: Reading Movie Objects
import java.io.*;
public class ReadMovieFromFile {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("Comedy.dat");
ObjectInputStream ois = new ObjectInputStream(fis)) {
Movie movie = (Movie) ois.readObject();
System.out.println("ID: " + movie.id + ", Genre: " + movie.genre);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
State After Reading
graph LR
A["File: Comedy.dat (binary)"] -->|"Read"| B["Object in memory:\nMovie(id=1, genre=comedy)"]Trace Table
| Step | Action | Memory State | Exception |
|---|---|---|---|
| 1 | Open FileInputStream |
File opened | None |
| 2 | Open ObjectInputStream |
Ready to read objects | None |
| 3 | ois.readObject() |
Movie object loaded | None |
| 4 | Close streams | File closed | None |
Comparing Byte and Character Streams
| Feature | Byte Streams (InputStream, OutputStream) |
Character Streams (Reader, Writer) |
|---|---|---|
| Data Type | Raw bytes (8-bit) | Characters (16-bit Unicode) |
| Classes | FileInputStream, FileOutputStream |
FileReader, FileWriter |
| Use Case | Binary files (images, executables) | Text files (CSV, JSON, logs) |
| Performance | Faster for binary data | Slower (converts bytes to chars) |
| Buffering | Use BufferedInputStream/BufferedOutputStream |
Use BufferedReader/BufferedWriter |
Exception Handling in File I/O
Common Exceptions
FileNotFoundException: Thrown when a file does not exist.IOException: General I/O errors (e.g., disk full, permission denied).EOFException: End of file reached unexpectedly.
Example: Handling Exceptions
import java.io.*;
public class HandleFileExceptions {
public static void main(String[] args) {
try {
FileReader fr = new FileReader("nonexistent.txt");
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
System.out.println(line);
} catch (FileNotFoundException e) {
System.err.println("File not found: " + e.getMessage());
} catch (IOException e) {
System.err.println("Error reading file: " + e.getMessage());
}
}
}
Trace Table for Exception Handling
| Step | Action | Exception Thrown | Handling |
|---|---|---|---|
| 1 | FileReader("nonexistent.txt") |
FileNotFoundException |
Caught, error printed |
| 2 | br.readLine() |
Not executed | - |
Practical Example: Daraz Order Queue
Scenario: Daraz processes orders in a FIFO (First-In-First-Out) manner using a queue stored in a file.
Code: Writing Orders to a File
import java.io.*;
import java.util.LinkedList;
import java.util.Queue;
public class DarazOrderQueue {
public static void main(String[] args) {
Queue<String> orders = new LinkedList<>();
orders.add("Order123: Laptop");
orders.add("Order124: Phone");
try (PrintWriter pw = new PrintWriter(new FileWriter("orders.txt"))) {
for (String order : orders) {
pw.println(order);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
State After Writing Orders
graph LR
A["File: orders.txt (before)"] -->|"Empty"| B["File: orders.txt (after)"]
B --> C["Order123: Laptop\nOrder124: Phone"]Code: Reading Orders from File
import java.io.*;
public class ProcessDarazOrders {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("orders.txt"))) {
String order;
while ((order = br.readLine()) != null) {
System.out.println("Processing: " + order);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Trace Table for Reading Orders
| Step | Action | File State | Output |
|---|---|---|---|
| 1 | Open BufferedReader |
File opened | - |
| 2 | br.readLine() (1st call) |
Reads "Order123: Laptop" | Prints "Processing: ..." |
| 3 | br.readLine() (2nd call) |
Reads "Order124: Phone" | Prints "Processing: ..." |
| 4 | br.readLine() (3rd call) |
Returns null (EOF) |
Loop ends |
File Handling with Scanner and PrintWriter
Example: Reading Integers and Writing to Files
Task: Read an integer and write it to pos.dat (positive) or neg.dat (negative).
import java.io.*;
import java.util.Scanner;
public class PositiveNegativeFile {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter an integer: ");
int num = scanner.nextInt();
try (PrintWriter pw = new PrintWriter(new FileWriter(num > 0 ? "pos.dat" : "neg.dat"))) {
pw.println(num);
System.out.println("Number written to " + (num > 0 ? "pos.dat" : "neg.dat"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
State After Writing
graph TD
A["Input: 42"] -->|"Positive"| B["File: pos.dat\n42"]
C["Input: -10"] -->|"Negative"| D["File: neg.dat\n-10"]File Handling with StringBuffer (Exam Tip)
Example: Writing Prime/Composite Strings
Task: Write a string to Prime.txt if its length is prime, else to Composite.txt.
import java.io.*;
public class PrimeCompositeFile {
public static boolean isPrime(int n) {
if (n <= 1) return false;
for (int i = 2; i <= Math.sqrt(n); i++) {
if (n % i == 0) return false;
}
return true;
}
public static void main(String[] args) {
String input = "HelloWorld";
String filename = isPrime(input.length()) ? "Prime.txt" : "Composite.txt";
try (PrintWriter pw = new PrintWriter(new FileWriter(filename))) {
pw.println(input);
System.out.println("String written to " + filename);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Trace Table
| Step | Action | File State | Condition Check |
|---|---|---|---|
| 1 | input.length() |
Length = 10 | Not prime (10 is composite) |
| 2 | Choose Composite.txt |
- | - |
| 3 | Write to Composite.txt |
File updated | - |
Exam Tip
File Handling Questions:
- Always use
try-with-resourcesto auto-close streams (avoidsNullPointerException). - For binary files, use
ObjectInputStream/ObjectOutputStream. - For text files, use
BufferedReader/BufferedWriterfor efficiency.
- Always use
Exception Handling:
- Declare
throws IOExceptionif not handling exceptions in the method. - Custom exceptions (like in the
Mobilephone number example) must extendExceptionorRuntimeException.
- Declare
Common Pitfalls:
- Forgetting to check if a file exists before writing (
file.exists()). - Not handling
FileNotFoundExceptionorIOException. - Mixing byte and character streams incorrectly (e.g., using
FileInputStreamfor text files).
- Forgetting to check if a file exists before writing (
Real-World Scenarios:
- Relate file handling to apps like eSewa (transaction logs), Daraz (order processing), or NTC (billing).
- For prime/composite string examples, mention how NEPSE (stock market) might log prime-numbered transactions.
Code Structure:
- Start with
import java.io.*;for all I/O classes. - Use
try-with-resourcesfor all file operations to ensure streams are closed. - Example starter template:
try (FileWriter fw = new FileWriter("filename.txt"); BufferedWriter bw = new BufferedWriter(fw)) { bw.write("data"); } catch (IOException e) { e.printStackTrace(); }
- Start with
Summary Checklist for Full Marks
- Used
try-with-resourcesfor all file operations. - Handled exceptions properly (
FileNotFoundException,IOException). - Chose the right stream type (byte vs. character).
- Included a trace table or state diagram for file operations.
- Related the example to a real-world scenario (e.g., Daraz orders, eSewa logs).
- Explained the purpose of each class (
File,FileInputStream,BufferedReader, etc.).
Based on the TU BITM syllabus for Object Oriented Programming With Java (IT234), unit 7.
Discussion
Loading…