IT234 Object Oriented Programming with Java

Object Oriented Programming with JavaUnit 714 min read

File I/O in Java: Streams, Files, and Serialization

Unit 7 of Object Oriented Programming with Java covers file handling techniques in Java, including stream types (byte/character), file operations (read/write), serialization, and best practices for robust I/O handling with error management.

TAKEAWAYS:

  • Understand stream types (input/output, byte/character) and their classes (FileInputStream, BufferedReader, etc.) with clear use cases.
  • Master file operations (create, read, write, delete) using File and FileWriter/FileReader with proper resource management.
  • Learn serialization to persist objects (Serializable interface, ObjectOutputStream) and its security implications.
  • Compare buffered vs. non-buffered streams for performance optimization.
  • Handle exceptions (IOException, FileNotFoundException) using try-with-resources for automatic cleanup.
  • Apply real-world scenarios like logging, data backup, and configuration files in Java applications.

1. Introduction to File I/O in Java

File I/O (Input/Output) allows Java programs to interact with external files and streams. This is essential for:

  • Storing data persistently (e.g., user profiles, transaction logs).
  • Reading configuration files (e.g., config.properties in apps like Khalti or Pathao).
  • Processing large datasets (e.g., NTC or NEPSE stock data).

Java provides two main approaches:

  1. Stream-based I/O: Uses InputStream/OutputStream (byte streams) and Reader/Writer (character streams).
  2. File-based I/O: Uses File class for file metadata and operations.

2. Stream Types in Java

Streams are sequences of data read from or written to a source/destination. They are categorized as:

Byte StreamCharacter StreamFileInputStreamFileOutputStreamFileReaderFileWriterBufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter
Hierarchy of Java I/O Streams (Byte vs. Character Streams)

A. Byte Streams vs. Character Streams

Byte Streams Character Streams
Handles raw bytes (InputStream, OutputStream). Handles Unicode characters (Reader, Writer).
Used for binary files (images, executables). Used for text files (.txt, .csv).
Example: FileInputStream, FileOutputStream. Example: FileReader, FileWriter.

Why it matters:

  • Ncell’s billing system uses byte streams to read binary data from SIM cards.
  • Daraz’s order processing uses character streams to log text-based order details in .csv files.

Visual: Stream Hierarchy

classDiagram
    class InputStream {
        +int read()
    }
    class OutputStream {
        +void write(int b)
    }
    class Reader {
        +int read()
    }
    class Writer {
        +void write(int c)
    }
    InputStream <|-- FileInputStream
    OutputStream <|-- FileOutputStream
    Reader <|-- FileReader
    Writer <|-- FileWriter
    FileInputStream --> BufferedInputStream
    FileOutputStream --> BufferedOutputStream
    FileReader --> BufferedReader
    FileWriter --> BufferedWriter

3. File Operations

The File class (in java.io) represents file/directory metadata but cannot read/write data directly. Use streams for that.

Hello, TU Students!0File I/O is easy with Java.1
State of `data.txt` after writing in FileDemo example (Step 3)

Key Methods

Method Description
File(String path) Creates a File object.
boolean createNewFile() Creates a new empty file.
boolean delete() Deletes the file.
boolean exists() Checks if the file exists.
long length() Returns file size in bytes.
String[] list() Lists files in a directory.

Example: Create and Write to a File

import java.io.FileWriter;
import java.io.IOException;

public class FileDemo {
    public static void main(String[] args) {
        try (FileWriter writer = new FileWriter("data.txt")) {
            writer.write("Hello, TU Students!\n");
            writer.write("File I/O is easy with Java.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Trace:

Step Action File Content (data.txt)
1 FileWriter opens data.txt. (Empty)
2 write("Hello...") Hello, TU Students!
3 write("File I/O...") Hello, TU Students!\nFile I/O...
4 try-with-resources closes file. (Content preserved)

Real-World Tie-In:

  • eSewa’s transaction logs are written to files using FileWriter to record payments securely.

4. Buffered Streams for Performance

Buffered streams reduce I/O operations by reading/writing data in chunks.

sequenceDiagram
    participant User
    participant BufferedWriter
    participant FileWriter
    participant data_txt
    User->>BufferedWriter: write("Buffered I/O is efficient!")
    BufferedWriter->>FileWriter: write()
    FileWriter->>data_txt: Buffer fills
    User->>BufferedWriter: newLine()
    BufferedWriter->>FileWriter: write("\n")
    User->>BufferedWriter: close()
    BufferedWriter->>FileWriter: flush()
    FileWriter->>data_txt: Writes to file
    alt Buffer full
        BufferedWriter->>FileWriter: flush()
    end
BufferedWriter flush mechanism during write operations

Comparison: Buffered vs. Non-Buffered

Feature FileWriter (Non-Buffered) BufferedWriter (Buffered)
Speed Slower (1 byte at a time). Faster (buffers data).
Memory Usage Low. Higher (temporary buffer).
Use Case Small files. Large files (e.g., logs).

Example: BufferedWriter

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedDemo {
    public static void main(String[] args) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("buffered.txt"))) {
            writer.write("Buffered I/O is efficient!\n");
            writer.newLine(); // Adds OS-specific newline.
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Trace:

Step Action Buffer State File Content (buffered.txt)
1 BufferedWriter initializes. Empty buffer. (Empty)
2 write("Buffered...") Buffer: "Buffered..." (Empty)
3 newLine() Buffer: "Buffered...\n" (Empty)
4 close() flushes buffer. Empty buffer. Buffered...\n

Real-World Tie-In:

  • NEPSE’s stock data processing uses BufferedReader to efficiently read large .csv files of daily trades.

5. Reading Files

A. Reading Text Files (BufferedReader)

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ReadFileDemo {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(new FileReader("data.txt"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Trace:

Step Action reader.readLine() Output
1 Opens data.txt. — —
2 readLine() "Hello, TU..." Hello, TU Students!
3 readLine() "File I/O..." File I/O is easy...
4 readLine() returns null. null (Loop ends)

B. Reading Binary Files (FileInputStream)

import java.io.FileInputStream;
import java.io.IOException;

public class BinaryReadDemo {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("image.png")) {
            int data;
            while ((data = fis.read()) != -1) {
                // Process binary data (e.g., write to another file).
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Real-World Tie-In:

  • Pathao’s ride data is stored in binary format for faster access during peak hours.

6. Serialization: Saving Objects to Files

Serialization converts objects into byte streams for storage/transmission. Use the Serializable interface.

0student1student21—2teacher13—
Serialized objects stored in a hash table (h(k) = k.hashCode() % 4, chaining)

Example: Serializing a Student Object

import java.io.*;

class Student implements Serializable {
    private String name;
    private int rollNo;

    public Student(String name, int rollNo) {
        this.name = name;
        this.rollNo = rollNo;
    }
}

public class SerializationDemo {
    public static void main(String[] args) {
        Student student = new Student("Ramesh", 101);

        // Serialize
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("student.ser"))) {
            oos.writeObject(student);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Deserialize
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("student.ser"))) {
            Student loadedStudent = (Student) ois.readObject();
            System.out.println("Loaded: " + loadedStudent.name);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Trace:

Step Action File (student.ser) Object State
1 writeObject(student) Binary data written. student serialized.
2 readObject() Binary data read. loadedStudent restored.

Real-World Tie-In:

  • Khalti’s user session data is serialized to temporarily store user login details during transactions.

7. Exception Handling in File I/O

Common exceptions:

  • FileNotFoundException: File does not exist.
  • IOException: General I/O errors (e.g., disk full).
  • ClassNotFoundException: During deserialization (if class definition is missing).

Best Practice: Use try-with-resources to auto-close streams.

try (Resource res = new Resource()) {
    // Code
} catch (Exception e) {
    e.printStackTrace();
}

8. File Handling Best Practices

  1. Always close resources: Use try-with-resources or finally blocks.
  2. Handle exceptions: Never ignore IOException.
  3. Use buffered streams: For large files, improve performance.
  4. Validate paths: Check File.exists() before operations.
  5. Security: Avoid deserializing untrusted data (risk of InvalidClassException).

In the Real World

  1. eSewa:

    • Uses FileWriter to log transactions in transactions.log for auditing.
    • Example: Every payment is appended to the file with a timestamp.
  2. NTC’s Billing System:

    • Employs BufferedReader to parse large .csv files of customer usage data.
    • Example: Reads 10,000 records in seconds for monthly billing.
  3. Pathao’s Driver App:

    • Serializes driver location data (Driver objects) to driver.ser for quick recovery after crashes.
    • Example: If the app crashes, the last known location is restored from the file.

Exam Tip

  1. Stream Types:

    • Know when to use byte streams (binary files) vs. character streams (text files).
    • Example question: "Which stream would you use to read a .jpg file?" → FileInputStream.
  2. File Operations:

    • Memorize File class methods (exists(), delete(), etc.).
    • Example question: "How do you check if a file exists in Java?" → file.exists().
  3. Serialization:

    • Understand Serializable and ObjectOutputStream.
    • Example question: "What happens if a class does not implement Serializable?" → NotSerializableException.
  4. Error Handling:

    • Always use try-with-resources in exams.
    • Example question: "Write code to safely read a file." → Include try-with-resources.
  5. Performance:

    • Compare buffered vs. non-buffered streams.
    • Example question: "Why is BufferedReader faster than FileReader?" → Reduces system calls.

Visual Summary: File I/O Workflow

flowchart TD
    A["Program"] --> B["Choose Stream Type<br/>(Byte/Character)"]
    B -->|"Byte"| C["FileInputStream<br/>FileOutputStream"]
    B -->|"Character"| D["FileReader<br/>FileWriter"]
    C --> E["BufferedInputStream<br/>BufferedOutputStream"]
    D --> F["BufferedReader<br/>BufferedWriter"]
    E --> G["Read/Write Binary Data"]
    F --> H["Read/Write Text Data"]
    G --> I["File Operations<br/>(create, delete, etc.)"]
    H --> I
    I --> J["Handle Exceptions<br/>(IOException)"]
    J --> K["Close Resources<br/>(try-with-resources)"]

In the real world

  • eSewa’s transaction logs: Uses BufferedWriter to efficiently write thousands of daily transactions in binary format (byte streams) for secure storage and quick retrieval.
  • NEPSE stock data processing: Employs BufferedReader to read large .csv files (character streams) of daily trade data, reducing I/O overhead for real-time analysis.
  • Ncell’s SIM card data: Leverages byte streams (FileInputStream) to read binary data from SIM cards for billing and customer profile management.

Based on the TU BIM syllabus for Object Oriented Programming with Java (IT234), unit 7.

Discussion

Loading…