Learning Objectives

Exception Handling

Understand exception hierarchy and handling mechanisms

Try-Catch Blocks

Master try-catch, finally, and try-with-resources

Custom Exceptions

Learn to create and use custom exception classes

File I/O Operations

Master file reading, writing, and management

Introduction to Exception Handling

What are Exceptions?

Exceptions are events that occur during the execution of a program that disrupt the normal flow of instructions. They represent error conditions or exceptional situations that need to be handled.

Exception vs C Error Handling

C

Return codes, error numbers, manual error checking

Java

Exception objects, automatic propagation, structured error handling

Exception Hierarchy

Throwable

Error (unchecked)
OutOfMemoryError
StackOverflowError
Exception (checked)
RuntimeException (unchecked)
NullPointerException
ArrayIndexOutOfBoundsException
IOException (checked)
FileNotFoundException

Checked vs Unchecked Exceptions

Checked Exceptions

Must be handled or declared (IOException, SQLException)

Unchecked Exceptions

Don't need to be handled (RuntimeException and its subclasses)

Basic Exception Handling

Try-Catch Block

The basic structure for handling exceptions.

try {
    // Code that might throw an exception
    int result = 10 / 0;  // This will throw ArithmeticException
} catch (ArithmeticException e) {
    // Handle the exception
    System.out.println("Error: Division by zero");
    System.out.println("Exception details: " + e.getMessage());
} catch (Exception e) {
    // Catch any other exceptions
    System.out.println("General error: " + e.getMessage());
}

Multiple Catch Blocks

You can have multiple catch blocks to handle different types of exceptions.

try {
    // Code that might throw different exceptions
    String str = null;
    int length = str.length();  // NullPointerException
    
    int[] array = {1, 2, 3};
    int value = array[10];      // ArrayIndexOutOfBoundsException
    
} catch (NullPointerException e) {
    System.out.println("String is null: " + e.getMessage());
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("Array index out of bounds: " + e.getMessage());
} catch (Exception e) {
    System.out.println("Unexpected error: " + e.getMessage());
}

Finally Block

The finally block always executes, regardless of whether an exception occurs.

try {
    // Code that might throw an exception
    File file = new File("test.txt");
    FileReader reader = new FileReader(file);
    
    // Read file content
    int character;
    while ((character = reader.read()) != -1) {
        System.out.print((char) character);
    }
    
} catch (FileNotFoundException e) {
    System.out.println("File not found: " + e.getMessage());
} catch (IOException e) {
    System.out.println("Error reading file: " + e.getMessage());
} finally {
    // This always executes
    System.out.println("Cleanup completed");
    // Close resources if they were opened
}

Try-With-Resources (Java 7+)

Automatically manages resource cleanup for classes that implement AutoCloseable.

try (FileReader reader = new FileReader("test.txt");
     BufferedReader bufferedReader = new BufferedReader(reader)) {
    
    String line;
    while ((line = bufferedReader.readLine()) != null) {
        System.out.println(line);
    }
    
} catch (IOException e) {
    System.out.println("Error reading file: " + e.getMessage());
}
// Resources are automatically closed here

Custom Exceptions

Creating Custom Exception Classes

You can create your own exception classes by extending Exception or RuntimeException.

public class InsufficientFundsException extends Exception {
    private double amount;
    private double balance;
    
    public InsufficientFundsException(double amount, double balance) {
        super("Insufficient funds. Required: " + amount + ", Available: " + balance);
        this.amount = amount;
        this.balance = balance;
    }
    
    public double getAmount() {
        return amount;
    }
    
    public double getBalance() {
        return balance;
    }
}

Using Custom Exceptions

public class BankAccount {
    private double balance;
    
    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }
    
    public void withdraw(double amount) throws InsufficientFundsException {
        if (amount > balance) {
            throw new InsufficientFundsException(amount, balance);
        }
        balance -= amount;
    }
    
    public double getBalance() {
        return balance;
    }
}

public class BankDemo {
    public static void main(String[] args) {
        BankAccount account = new BankAccount(1000.0);
        
        try {
            account.withdraw(1500.0);
        } catch (InsufficientFundsException e) {
            System.out.println("Exception: " + e.getMessage());
            System.out.println("Required amount: " + e.getAmount());
            System.out.println("Available balance: " + e.getBalance());
        }
    }
}

File I/O Basics

File Class

The File class represents file and directory pathnames.

import java.io.File;

public class FileOperations {
    public static void main(String[] args) {
        // Create a File object
        File file = new File("test.txt");
        
        // Check if file exists
        if (file.exists()) {
            System.out.println("File exists");
            System.out.println("File size: " + file.length() + " bytes");
            System.out.println("Is file: " + file.isFile());
            System.out.println("Is directory: " + file.isDirectory());
        } else {
            System.out.println("File does not exist");
        }
        
        // Create directory
        File directory = new File("mydir");
        if (!directory.exists()) {
            boolean created = directory.mkdir();
            System.out.println("Directory created: " + created);
        }
    }
}

FileReader and FileWriter

Basic character-based file I/O.

import java.io.*;

public class TextFileProcessor {
    public static void writeToFile(String filename, String content) {
        try (FileWriter writer = new FileWriter(filename)) {
            writer.write(content);
            System.out.println("Content written to file successfully");
        } catch (IOException e) {
            System.out.println("Error writing to file: " + e.getMessage());
        }
    }
    
    public static String readFromFile(String filename) {
        StringBuilder content = new StringBuilder();
        
        try (FileReader reader = new FileReader(filename)) {
            int character;
            while ((character = reader.read()) != -1) {
                content.append((char) character);
            }
        } catch (IOException e) {
            System.out.println("Error reading file: " + e.getMessage());
            return null;
        }
        
        return content.toString();
    }
}

BufferedReader and BufferedWriter

More efficient reading and writing with buffering.

import java.io.*;

public class BufferedFileProcessor {
    public static void writeLines(String filename, List lines) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
            for (String line : lines) {
                writer.write(line);
                writer.newLine();
            }
            System.out.println("Lines written to file successfully");
        } catch (IOException e) {
            System.out.println("Error writing to file: " + e.getMessage());
        }
    }
    
    public static List readLines(String filename) {
        List lines = new ArrayList<>();
        
        try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line);
            }
        } catch (IOException e) {
            System.out.println("Error reading file: " + e.getMessage());
            return null;
        }
        
        return lines;
    }
}

Practical Examples

Configuration File Manager

import java.io.*;
import java.util.*;

public class ConfigManager {
    private Map config;
    private String configFile;
    
    public ConfigManager(String filename) {
        this.configFile = filename;
        this.config = new HashMap<>();
        loadConfig();
    }
    
    public void loadConfig() {
        try (BufferedReader reader = new BufferedReader(new FileReader(configFile))) {
            String line;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (!line.isEmpty() && !line.startsWith("#")) {
                    String[] parts = line.split("=", 2);
                    if (parts.length == 2) {
                        config.put(parts[0].trim(), parts[1].trim());
                    }
                }
            }
        } catch (IOException e) {
            System.out.println("Error loading config: " + e.getMessage());
        }
    }
    
    public void saveConfig() {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(configFile))) {
            for (Map.Entry entry : config.entrySet()) {
                writer.write(entry.getKey() + "=" + entry.getValue());
                writer.newLine();
            }
        } catch (IOException e) {
            System.out.println("Error saving config: " + e.getMessage());
        }
    }
    
    public String getValue(String key) {
        return config.get(key);
    }
    
    public void setValue(String key, String value) {
        config.put(key, value);
    }
}

Key Differences from C

Concept C Java
Error Handling Return codes, errno Exception objects
Resource Management Manual cleanup Automatic with try-with-resources
File I/O FILE pointers, manual buffering Stream classes, automatic buffering
Exception Types No built-in types Rich exception hierarchy
Memory Management Manual (malloc/free) Automatic garbage collection
Error Propagation Manual checking Automatic stack unwinding

Summary

In this module, you've learned:

  • ? How to handle exceptions using try-catch blocks
  • ? The difference between checked and unchecked exceptions
  • ? How to create and use custom exception classes
  • ? File I/O operations using various approaches
  • ? Input/output streams and their usage
  • ? Best practices for exception handling and file operations
  • ? Key differences between Java exception handling and C error handling

Next Steps

  1. Complete the exercises in the exercises.md file
  2. Practice exception handling and file operations
  3. Move to Module 8: Multithreading and Concurrency

?? Module 7 Complete!

You now have a solid understanding of exception handling and file I/O. Time to learn about multithreading!