Skip to main content
  1. Resources/
  2. Study Materials/
  3. Information & Communication Technology Engineering/
  4. ICT Semester 4/
  5. Java Programming (4343203)/

21 mins· ·
Milav Dabgar
Author
Milav Dabgar
Experienced lecturer in the electrical and electronic manufacturing industry. Skilled in Embedded Systems, Image Processing, Data Science, MATLAB, Python, STM32. Strong education professional with a Master’s degree in Communication Systems Engineering from L.D. College of Engineering - Ahmedabad.
Lecture 19: Input/Output and File Handling | Java Programming (4343203)

Input/Output and File Handling

Java Programming (4343203)

Lecture 19

Unit 5: Advanced Java - I/O Operations
GTU Computer Engineering Semester 4

Learning Objectives

  • Understand Java I/O stream hierarchy and classification
  • Master byte streams and character streams
  • Implement file operations (create, read, write, delete)
  • Work with directories and file metadata
  • Apply buffered I/O for performance optimization
  • Implement object serialization and deserialization
Focus: Efficient data input/output operations and persistent storage using Java's comprehensive I/O framework.

Java I/O Stream Hierarchy

Stream Classification

  • Byte Streams: Handle raw binary data (8-bit)
  • Character Streams: Handle text data (16-bit Unicode)
  • Input Streams: Read data from source
  • Output Streams: Write data to destination

Key Differences

AspectByte StreamsCharacter Streams
Data Unit8-bit bytes16-bit characters
Base ClassesInputStream/OutputStreamReader/Writer
Use CaseBinary data, images, audioText files, Unicode
I/O Stream Hierarchy:

Byte Streams:
InputStream
├── FileInputStream
├── BufferedInputStream
├── DataInputStream
└── ObjectInputStream

OutputStream
├── FileOutputStream
├── BufferedOutputStream
├── DataOutputStream
└── ObjectOutputStream

Character Streams:
Reader
├── FileReader
├── BufferedReader
└── StringReader

Writer
├── FileWriter
├── BufferedWriter
├── PrintWriter
└── StringWriter

File Class for File and Directory Operations


import java.io.File;
import java.io.IOException;
import java.util.Date;

public class FileClassDemo {
    public static void main(String[] args) {
        System.out.println("=== File Class Demonstration ===\n");
        
        // Create File objects
        File file = new File("example.txt");
        File directory = new File("testdir");
        File nestedFile = new File(directory, "nested.txt");
        
        demonstrateFileProperties(file);
        demonstrateDirectoryOperations(directory);
        demonstrateFileOperations(file, nestedFile);
    }
    
    private static void demonstrateFileProperties(File file) {
        System.out.println("--- File Properties ---");
        
        System.out.println("File name: " + file.getName());
        System.out.println("Absolute path: " + file.getAbsolutePath());
        System.out.println("Parent directory: " + file.getParent());
        System.out.println("File exists: " + file.exists());
        System.out.println("Is file: " + file.isFile());
        System.out.println("Is directory: " + file.isDirectory());
        System.out.println("Can read: " + file.canRead());
        System.out.println("Can write: " + file.canWrite());
        System.out.println("Can execute: " + file.canExecute());
        System.out.println("Is hidden: " + file.isHidden());
        
        if (file.exists()) {
            System.out.println("File size: " + file.length() + " bytes");
            System.out.println("Last modified: " + new Date(file.lastModified()));
        }
        
        System.out.println();
    }
    
    private static void demonstrateDirectoryOperations(File directory) {
        System.out.println("--- Directory Operations ---");
        
        // Create directory
        if (!directory.exists()) {
            boolean created = directory.mkdir(); // Creates single directory
            // boolean created = directory.mkdirs(); // Creates parent directories too
            System.out.println("Directory created: " + created);
        } else {
            System.out.println("Directory already exists");
        }
        
        // List directory contents
        if (directory.exists() && directory.isDirectory()) {
            System.out.println("Directory contents:");
            String[] contents = directory.list();
            if (contents != null) {
                for (String item : contents) {
                    File itemFile = new File(directory, item);
                    System.out.printf("  %s %s%n", 
                                    itemFile.isDirectory() ? "[DIR]" : "[FILE]", 
                                    item);
                }
            } else {
                System.out.println("  Directory is empty or cannot be read");
            }
            
            // Alternative: Get File objects
            File[] files = directory.listFiles();
            if (files != null) {
                System.out.println("Total items: " + files.length);
            }
        }
        
        System.out.println();
    }
    
    private static void demonstrateFileOperations(File file, File nestedFile) {
        System.out.println("--- File Operations ---");
        
        try {
            // Create new file
            if (!file.exists()) {
                boolean created = file.createNewFile();
                System.out.println("File created: " + created);
            } else {
                System.out.println("File already exists");
            }
            
            // Create nested file
            if (!nestedFile.getParentFile().exists()) {
                nestedFile.getParentFile().mkdirs();
            }
            if (!nestedFile.exists()) {
                boolean nestedCreated = nestedFile.createNewFile();
                System.out.println("Nested file created: " + nestedCreated);
            }
            
            // File permissions
            file.setReadOnly();
            System.out.println("File set to read-only");
            
            file.setWritable(true);
            System.out.println("File write permission restored");
            
            // Copy file (using renameTo)
            File copyFile = new File("example_copy.txt");
            // Note: renameTo is platform dependent and may not work across filesystems
            
            // File comparison
            System.out.println("Files are same: " + file.equals(nestedFile));
            
        } catch (IOException e) {
            System.err.println("I/O error: " + e.getMessage());
        }
        
        System.out.println();
    }
}
                

Byte Streams - FileInputStream and FileOutputStream


import java.io.*;

public class ByteStreamsDemo {
    public static void main(String[] args) {
        System.out.println("=== Byte Streams Demonstration ===\n");
        
        String fileName = "binary_data.txt";
        
        // Write data using FileOutputStream
        writeDataUsingByteStream(fileName);
        
        // Read data using FileInputStream
        readDataUsingByteStream(fileName);
        
        // Copy file using byte streams
        copyFileUsingByteStreams(fileName, "binary_data_copy.txt");
        
        // Demonstrate buffered streams
        demonstrateBufferedByteStreams();
    }
    
    private static void writeDataUsingByteStream(String fileName) {
        System.out.println("--- Writing Data Using FileOutputStream ---");
        
        try (FileOutputStream fos = new FileOutputStream(fileName)) {
            // Write single byte
            fos.write(65); // ASCII value of 'A'
            
            // Write byte array
            String text = "Hello, Byte Streams!\n";
            byte[] data = text.getBytes();
            fos.write(data);
            
            // Write part of byte array
            String moreText = "Java I/O Programming";
            byte[] moreData = moreText.getBytes();
            fos.write(moreData, 0, 4); // Write "Java"
            
            System.out.println("Data written to " + fileName);
            
        } catch (IOException e) {
            System.err.println("Error writing to file: " + e.getMessage());
        }
    }
    
    private static void readDataUsingByteStream(String fileName) {
        System.out.println("--- Reading Data Using FileInputStream ---");
        
        try (FileInputStream fis = new FileInputStream(fileName)) {
            System.out.println("File size: " + fis.available() + " bytes");
            
            // Method 1: Read single byte
            System.out.print("Reading byte by byte: ");
            int byteData;
            int count = 0;
            while ((byteData = fis.read()) != -1 && count < 5) {
                System.out.print((char) byteData);
                count++;
            }
            System.out.println();
            
            // Reset for next read method
        } catch (IOException e) {
            System.err.println("Error reading file: " + e.getMessage());
        }
        
        // Method 2: Read entire file into byte array
        try (FileInputStream fis = new FileInputStream(fileName)) {
            byte[] buffer = new byte[fis.available()];
            int bytesRead = fis.read(buffer);
            
            System.out.println("Bytes read: " + bytesRead);
            System.out.println("Content as string: " + new String(buffer));
            
        } catch (IOException e) {
            System.err.println("Error reading file: " + e.getMessage());
        }
        
        // Method 3: Read with buffer
        try (FileInputStream fis = new FileInputStream(fileName)) {
            byte[] buffer = new byte[10]; // Small buffer for demonstration
            int bytesRead;
            
            System.out.print("Reading with buffer: ");
            while ((bytesRead = fis.read(buffer)) != -1) {
                System.out.print(new String(buffer, 0, bytesRead));
            }
            System.out.println();
            
        } catch (IOException e) {
            System.err.println("Error reading file: " + e.getMessage());
        }
        
        System.out.println();
    }
    
    private static void copyFileUsingByteStreams(String sourceFile, String destFile) {
        System.out.println("--- Copying File Using Byte Streams ---");
        
        try (FileInputStream fis = new FileInputStream(sourceFile);
             FileOutputStream fos = new FileOutputStream(destFile)) {
            
            byte[] buffer = new byte[1024]; // 1KB buffer
            int bytesRead;
            int totalBytes = 0;
            
            while ((bytesRead = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
                totalBytes += bytesRead;
            }
            
            System.out.println("File copied successfully");
            System.out.println("Total bytes copied: " + totalBytes);
            
        } catch (IOException e) {
            System.err.println("Error copying file: " + e.getMessage());
        }
        
        System.out.println();
    }
    
    private static void demonstrateBufferedByteStreams() {
        System.out.println("--- Buffered Byte Streams ---");
        
        String fileName = "buffered_test.txt";
        
        // Write using BufferedOutputStream
        try (BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream(fileName))) {
            
            String data = "Buffered streams improve performance by reducing system calls.\n";
            for (int i = 0; i < 5; i++) {
                bos.write(data.getBytes());
            }
            
            // Flush is automatic when closing, but can be done manually
            bos.flush();
            System.out.println("Data written using BufferedOutputStream");
            
        } catch (IOException e) {
            System.err.println("Error with buffered output: " + e.getMessage());
        }
        
        // Read using BufferedInputStream
        try (BufferedInputStream bis = new BufferedInputStream(
                new FileInputStream(fileName))) {
            
            byte[] buffer = new byte[50];
            int bytesRead;
            
            System.out.println("Reading using BufferedInputStream:");
            while ((bytesRead = bis.read(buffer)) != -1) {
                System.out.print(new String(buffer, 0, bytesRead));
            }
            
        } catch (IOException e) {
            System.err.println("Error with buffered input: " + e.getMessage());
        }
        
        System.out.println();
    }
}
                

Character Streams - FileReader and FileWriter


import java.io.*;

public class CharacterStreamsDemo {
    public static void main(String[] args) {
        System.out.println("=== Character Streams Demonstration ===\n");
        
        String fileName = "text_data.txt";
        
        // Write data using FileWriter
        writeDataUsingCharacterStream(fileName);
        
        // Read data using FileReader
        readDataUsingCharacterStream(fileName);
        
        // Demonstrate BufferedReader and BufferedWriter
        demonstrateBufferedCharacterStreams();
        
        // Demonstrate PrintWriter
        demonstratePrintWriter();
    }
    
    private static void writeDataUsingCharacterStream(String fileName) {
        System.out.println("--- Writing Data Using FileWriter ---");
        
        try (FileWriter fw = new FileWriter(fileName)) {
            // Write single character
            fw.write('H');
            
            // Write string
            fw.write("ello, Character Streams!\n");
            
            // Write character array
            char[] chars = {'J', 'a', 'v', 'a', ' '};
            fw.write(chars);
            
            // Write part of string
            String text = "I/O Programming is powerful!";
            fw.write(text, 0, 3); // Write "I/O"
            
            fw.write("\n");
            
            // Write multiple lines
            String[] lines = {
                "Line 1: Introduction to I/O",
                "Line 2: Character streams handle Unicode",
                "Line 3: Perfect for text processing"
            };
            
            for (String line : lines) {
                fw.write(line + "\n");
            }
            
            System.out.println("Text data written to " + fileName);
            
        } catch (IOException e) {
            System.err.println("Error writing to file: " + e.getMessage());
        }
    }
    
    private static void readDataUsingCharacterStream(String fileName) {
        System.out.println("--- Reading Data Using FileReader ---");
        
        // Method 1: Read character by character
        try (FileReader fr = new FileReader(fileName)) {
            System.out.print("First 20 characters: ");
            int charData;
            int count = 0;
            while ((charData = fr.read()) != -1 && count < 20) {
                System.out.print((char) charData);
                count++;
            }
            System.out.println();
            
        } catch (IOException e) {
            System.err.println("Error reading file: " + e.getMessage());
        }
        
        // Method 2: Read into character array
        try (FileReader fr = new FileReader(fileName)) {
            char[] buffer = new char[50];
            int charsRead = fr.read(buffer);
            
            System.out.println("Characters read: " + charsRead);
            System.out.println("Content: " + new String(buffer, 0, charsRead));
            
        } catch (IOException e) {
            System.err.println("Error reading file: " + e.getMessage());
        }
        
        System.out.println();
    }
    
    private static void demonstrateBufferedCharacterStreams() {
        System.out.println("--- Buffered Character Streams ---");
        
        String fileName = "buffered_text.txt";
        
        // Write using BufferedWriter
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(fileName))) {
            bw.write("BufferedWriter improves performance");
            bw.newLine(); // Platform-independent line separator
            bw.write("It reduces the number of system calls");
            bw.newLine();
            bw.write("Especially useful for writing multiple lines");
            
            System.out.println("Data written using BufferedWriter");
            
        } catch (IOException e) {
            System.err.println("Error with buffered writer: " + e.getMessage());
        }
        
        // Read using BufferedReader
        try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
            System.out.println("Reading using BufferedReader:");
            
            String line;
            int lineNumber = 1;
            while ((line = br.readLine()) != null) {
                System.out.println("Line " + lineNumber + ": " + line);
                lineNumber++;
            }
            
        } catch (IOException e) {
            System.err.println("Error with buffered reader: " + e.getMessage());
        }
        
        System.out.println();
    }
    
    private static void demonstratePrintWriter() {
        System.out.println("--- PrintWriter Demonstration ---");
        
        String fileName = "print_writer_demo.txt";
        
        try (PrintWriter pw = new PrintWriter(new FileWriter(fileName))) {
            // PrintWriter provides convenient methods
            pw.println("PrintWriter is very convenient for formatted output");
            pw.printf("Formatted number: %.2f%n", 3.14159);
            pw.printf("Formatted string: %s has %d characters%n", "Java", 4);
            
            // Write different data types
            pw.println(42);
            pw.println(true);
            pw.println('X');
            
            // Check for errors (PrintWriter doesn't throw exceptions)
            if (pw.checkError()) {
                System.err.println("An error occurred while writing");
            } else {
                System.out.println("Data written using PrintWriter");
            }
            
        } catch (IOException e) {
            System.err.println("Error with PrintWriter: " + e.getMessage());
        }
        
        // Read and display the content
        try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
            System.out.println("Content written by PrintWriter:");
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println("  " + line);
            }
            
        } catch (IOException e) {
            System.err.println("Error reading PrintWriter output: " + e.getMessage());
        }
        
        System.out.println();
    }
}
                

Data Streams for Primitive Types


import java.io.*;

public class DataStreamsDemo {
    public static void main(String[] args) {
        System.out.println("=== Data Streams Demonstration ===\n");
        
        String fileName = "primitive_data.dat";
        
        // Write primitive data
        writePrimitiveData(fileName);
        
        // Read primitive data
        readPrimitiveData(fileName);
    }
    
    private static void writePrimitiveData(String fileName) {
        System.out.println("--- Writing Primitive Data ---");
        
        try (DataOutputStream dos = new DataOutputStream(
                new BufferedOutputStream(new FileOutputStream(fileName)))) {
            
            // Write different primitive types
            dos.writeBoolean(true);
            dos.writeByte(127);
            dos.writeShort(32767);
            dos.writeInt(2147483647);
            dos.writeLong(9223372036854775807L);
            dos.writeFloat(3.14159f);
            dos.writeDouble(2.718281828459);
            dos.writeChar('J');
            dos.writeUTF("Hello, DataOutputStream!"); // Modified UTF-8
            
            // Write arrays
            int[] numbers = {1, 2, 3, 4, 5};
            dos.writeInt(numbers.length); // Write array length first
            for (int num : numbers) {
                dos.writeInt(num);
            }
            
            // Write a string array
            String[] words = {"Java", "I/O", "Streams", "Data"};
            dos.writeInt(words.length);
            for (String word : words) {
                dos.writeUTF(word);
            }
            
            System.out.println("Primitive data written to " + fileName);
            
        } catch (IOException e) {
            System.err.println("Error writing primitive data: " + e.getMessage());
        }
    }
    
    private static void readPrimitiveData(String fileName) {
        System.out.println("--- Reading Primitive Data ---");
        
        try (DataInputStream dis = new DataInputStream(
                new BufferedInputStream(new FileInputStream(fileName)))) {
            
            // Read in the same order as written
            boolean boolValue = dis.readBoolean();
            byte byteValue = dis.readByte();
            short shortValue = dis.readShort();
            int intValue = dis.readInt();
            long longValue = dis.readLong();
            float floatValue = dis.readFloat();
            double doubleValue = dis.readDouble();
            char charValue = dis.readChar();
            String stringValue = dis.readUTF();
            
            // Display the values
            System.out.println("Boolean: " + boolValue);
            System.out.println("Byte: " + byteValue);
            System.out.println("Short: " + shortValue);
            System.out.println("Int: " + intValue);
            System.out.println("Long: " + longValue);
            System.out.println("Float: " + floatValue);
            System.out.println("Double: " + doubleValue);
            System.out.println("Char: " + charValue);
            System.out.println("String: " + stringValue);
            
            // Read array
            int arrayLength = dis.readInt();
            int[] numbers = new int[arrayLength];
            for (int i = 0; i < arrayLength; i++) {
                numbers[i] = dis.readInt();
            }
            System.out.print("Integer array: ");
            for (int num : numbers) {
                System.out.print(num + " ");
            }
            System.out.println();
            
            // Read string array
            int stringArrayLength = dis.readInt();
            String[] words = new String[stringArrayLength];
            for (int i = 0; i < stringArrayLength; i++) {
                words[i] = dis.readUTF();
            }
            System.out.print("String array: ");
            for (String word : words) {
                System.out.print(word + " ");
            }
            System.out.println();
            
        } catch (IOException e) {
            System.err.println("Error reading primitive data: " + e.getMessage());
        }
        
        System.out.println();
    }
}

// Student class for object demonstration
class Student implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private String name;
    private int age;
    private double gpa;
    
    public Student(String name, int age, double gpa) {
        this.name = name;
        this.age = age;
        this.gpa = gpa;
    }
    
    @Override
    public String toString() {
        return String.format("Student{name='%s', age=%d, gpa=%.2f}", name, age, gpa);
    }
    
    // Getters
    public String getName() { return name; }
    public int getAge() { return age; }
    public double getGpa() { return gpa; }
}
                

Object Serialization and Deserialization


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

public class SerializationDemo {
    public static void main(String[] args) {
        System.out.println("=== Object Serialization Demonstration ===\n");
        
        String fileName = "students.ser";
        
        // Create sample data
        List students = createSampleStudents();
        
        // Serialize objects
        serializeObjects(students, fileName);
        
        // Deserialize objects
        deserializeObjects(fileName);
        
        // Demonstrate custom serialization
        demonstrateCustomSerialization();
    }
    
    private static List createSampleStudents() {
        List students = new ArrayList<>();
        students.add(new Student("Alice Johnson", 20, 3.8));
        students.add(new Student("Bob Smith", 19, 3.6));
        students.add(new Student("Charlie Brown", 21, 3.9));
        students.add(new Student("Diana Prince", 20, 3.7));
        return students;
    }
    
    private static void serializeObjects(List students, String fileName) {
        System.out.println("--- Serializing Objects ---");
        
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new BufferedOutputStream(new FileOutputStream(fileName)))) {
            
            // Serialize the entire list
            oos.writeObject(students);
            
            // Serialize individual objects
            oos.writeInt(students.size());
            for (Student student : students) {
                oos.writeObject(student);
            }
            
            // Serialize other data types
            oos.writeObject(new Date());
            oos.writeObject("Serialization timestamp");
            
            System.out.println("Objects serialized to " + fileName);
            System.out.println("Serialized " + students.size() + " students");
            
        } catch (IOException e) {
            System.err.println("Error serializing objects: " + e.getMessage());
        }
    }
    
    @SuppressWarnings("unchecked")
    private static void deserializeObjects(String fileName) {
        System.out.println("--- Deserializing Objects ---");
        
        try (ObjectInputStream ois = new ObjectInputStream(
                new BufferedInputStream(new FileInputStream(fileName)))) {
            
            // Deserialize the list
            List studentList = (List) ois.readObject();
            System.out.println("Deserialized student list:");
            for (Student student : studentList) {
                System.out.println("  " + student);
            }
            
            // Deserialize individual objects
            int count = ois.readInt();
            System.out.println("\nDeserializing " + count + " individual students:");
            for (int i = 0; i < count; i++) {
                Student student = (Student) ois.readObject();
                System.out.println("  " + (i + 1) + ". " + student);
            }
            
            // Deserialize other objects
            Date timestamp = (Date) ois.readObject();
            String message = (String) ois.readObject();
            
            System.out.println("\nTimestamp: " + timestamp);
            System.out.println("Message: " + message);
            
        } catch (IOException | ClassNotFoundException e) {
            System.err.println("Error deserializing objects: " + e.getMessage());
        }
        
        System.out.println();
    }
    
    private static void demonstrateCustomSerialization() {
        System.out.println("--- Custom Serialization ---");
        
        String fileName = "custom_serialization.ser";
        
        try {
            // Create a custom serializable object
            BankAccount account = new BankAccount("12345", "John Doe", 5000.0, "secret123");
            
            System.out.println("Original account: " + account);
            
            // Serialize
            try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) {
                oos.writeObject(account);
                System.out.println("Account serialized");
            }
            
            // Deserialize
            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName))) {
                BankAccount deserializedAccount = (BankAccount) ois.readObject();
                System.out.println("Deserialized account: " + deserializedAccount);
            }
            
        } catch (IOException | ClassNotFoundException e) {
            System.err.println("Error with custom serialization: " + e.getMessage());
        }
    }
}

// Custom serializable class with sensitive data
class BankAccount implements Serializable {
    private static final long serialVersionUID = 2L;
    
    private String accountNumber;
    private String holderName;
    private double balance;
    private transient String pin; // transient = won't be serialized
    
    public BankAccount(String accountNumber, String holderName, double balance, String pin) {
        this.accountNumber = accountNumber;
        this.holderName = holderName;
        this.balance = balance;
        this.pin = pin;
    }
    
    // Custom serialization method
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject(); // Serialize non-transient fields
        // Custom logic: encrypt PIN before serialization (simplified)
        String encryptedPin = "encrypted_" + pin;
        out.writeObject(encryptedPin);
        System.out.println("Custom writeObject called - PIN encrypted");
    }
    
    // Custom deserialization method
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject(); // Deserialize non-transient fields
        // Custom logic: decrypt PIN after deserialization (simplified)
        String encryptedPin = (String) in.readObject();
        this.pin = encryptedPin.replace("encrypted_", "");
        System.out.println("Custom readObject called - PIN decrypted");
    }
    
    @Override
    public String toString() {
        return String.format("BankAccount{accountNumber='%s', holderName='%s', balance=%.2f, pin='%s'}", 
                           accountNumber, holderName, balance, pin != null ? "****" : "null");
    }
}
                

GTU Previous Year Question (Summer 2022)

Q: Write a Java program to demonstrate file operations. The program should create a text file, write student information (name, roll number, marks) to the file, read the file content, and display it. Also implement functionality to append new student data to the existing file.

Solution:


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

// Student class to represent student data
class StudentInfo {
    private String name;
    private String rollNumber;
    private double marks;
    
    public StudentInfo(String name, String rollNumber, double marks) {
        this.name = name;
        this.rollNumber = rollNumber;
        this.marks = marks;
    }
    
    // Convert to file format string
    public String toFileString() {
        return String.format("%s|%s|%.2f", name, rollNumber, marks);
    }
    
    // Create from file format string
    public static StudentInfo fromFileString(String fileString) {
        String[] parts = fileString.split("\\|");
        if (parts.length == 3) {
            return new StudentInfo(parts[0], parts[1], Double.parseDouble(parts[2]));
        }
        return null;
    }
    
    @Override
    public String toString() {
        return String.format("Name: %-20s | Roll: %-10s | Marks: %6.2f", name, rollNumber, marks);
    }
    
    // Getters
    public String getName() { return name; }
    public String getRollNumber() { return rollNumber; }
    public double getMarks() { return marks; }
}

public class FileOperationsDemo {
    private static final String FILENAME = "students.txt";
    private static Scanner scanner = new Scanner(System.in);
    
    public static void main(String[] args) {
        System.out.println("=== Student File Operations System ===\n");
        
        boolean running = true;
        while (running) {
            displayMenu();
            int choice = getChoice();
            
            switch (choice) {
                case 1:
                    createAndWriteFile();
                    break;
                case 2:
                    readAndDisplayFile();
                    break;
                case 3:
                    appendStudentData();
                    break;
                case 4:
                    searchStudent();
                    break;
                case 5:
                    displayStatistics();
                    break;
                case 6:
                    backupFile();
                    break;
                case 7:
                    running = false;
                    System.out.println("Program terminated.");
                    break;
                default:
                    System.out.println("Invalid choice! Please try again.");
            }
            
            if (running) {
                System.out.println("\nPress Enter to continue...");
                scanner.nextLine();
            }
        }
        
        scanner.close();
    }
    
    private static void displayMenu() {
        System.out.println("\n" + "=".repeat(50));
        System.out.println("STUDENT MANAGEMENT SYSTEM");
        System.out.println("=".repeat(50));
        System.out.println("1. Create new file and add students");
        System.out.println("2. Read and display all students");
        System.out.println("3. Append new student data");
        System.out.println("4. Search for a student");
        System.out.println("5. Display statistics");
        System.out.println("6. Backup file");
        System.out.println("7. Exit");
        System.out.println("=".repeat(50));
        System.out.print("Enter your choice (1-7): ");
    }
    
    private static int getChoice() {
        try {
            int choice = Integer.parseInt(scanner.nextLine().trim());
            return choice;
        } catch (NumberFormatException e) {
            return -1; // Invalid choice
        }
    }
    
    private static void createAndWriteFile() {
        System.out.println("\n--- Create New File and Add Students ---");
        
        List students = new ArrayList<>();
        
        System.out.print("How many students do you want to add? ");
        int count;
        try {
            count = Integer.parseInt(scanner.nextLine().trim());
        } catch (NumberFormatException e) {
            System.out.println("Invalid number! Using default of 3.");
            count = 3;
        }
        
        // Collect student information
        for (int i = 1; i <= count; i++) {
            System.out.println("\nEnter details for Student " + i + ":");
            
            System.out.print("Name: ");
            String name = scanner.nextLine().trim();
            
            System.out.print("Roll Number: ");
            String rollNumber = scanner.nextLine().trim();
            
            System.out.print("Marks: ");
            double marks;
            try {
                marks = Double.parseDouble(scanner.nextLine().trim());
            } catch (NumberFormatException e) {
                System.out.println("Invalid marks! Using 0.0");
                marks = 0.0;
            }
            
            students.add(new StudentInfo(name, rollNumber, marks));
        }
        
        // Write to file using FileWriter (character stream)
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(FILENAME))) {
            // Write header
            writer.write("# Student Information File");
            writer.newLine();
            writer.write("# Format: Name|RollNumber|Marks");
            writer.newLine();
            writer.write("# Created on: " + new Date());
            writer.newLine();
            writer.newLine();
            
            // Write student data
            for (StudentInfo student : students) {
                writer.write(student.toFileString());
                writer.newLine();
            }
            
            System.out.println("\n✓ File created successfully!");
            System.out.println("✓ " + students.size() + " students written to " + FILENAME);
            
        } catch (IOException e) {
            System.err.println("✗ Error creating file: " + e.getMessage());
        }
    }
    
    private static void readAndDisplayFile() {
        System.out.println("\n--- Reading and Displaying All Students ---");
        
        File file = new File(FILENAME);
        if (!file.exists()) {
            System.out.println("✗ File " + FILENAME + " does not exist!");
            System.out.println("  Please create the file first using option 1.");
            return;
        }
        
        try (BufferedReader reader = new BufferedReader(new FileReader(FILENAME))) {
            String line;
            List students = new ArrayList<>();
            int lineNumber = 0;
            
            System.out.println("File Contents:");
            System.out.println("-".repeat(80));
            
            while ((line = reader.readLine()) != null) {
                lineNumber++;
                
                // Skip comments and empty lines
                if (line.startsWith("#") || line.trim().isEmpty()) {
                    System.out.println("Line " + lineNumber + ": " + line);
                    continue;
                }
                
                // Parse student data
                StudentInfo student = StudentInfo.fromFileString(line);
                if (student != null) {
                    students.add(student);
                    System.out.println("Line " + lineNumber + ": " + line);
                } else {
                    System.out.println("Line " + lineNumber + ": [Invalid format] " + line);
                }
            }
            
            System.out.println("-".repeat(80));
            
            // Display formatted student information
            if (!students.isEmpty()) {
                System.out.println("\nFormatted Student Information:");
                System.out.println("=".repeat(80));
                System.out.printf("%-4s | %-20s | %-10s | %-8s%n", "No.", "Name", "Roll No.", "Marks");
                System.out.println("-".repeat(80));
                
                for (int i = 0; i < students.size(); i++) {
                    StudentInfo student = students.get(i);
                    System.out.printf("%-4d | %-20s | %-10s | %8.2f%n", 
                                    i + 1, student.getName(), student.getRollNumber(), student.getMarks());
                }
                
                System.out.println("=".repeat(80));
                System.out.println("Total students: " + students.size());
            } else {
                System.out.println("\nNo valid student records found in the file.");
            }
            
        } catch (IOException e) {
            System.err.println("✗ Error reading file: " + e.getMessage());
        }
    }
}
                

Append and Search Implementation:


    private static void appendStudentData() {
        System.out.println("\n--- Append New Student Data ---");
        
        File file = new File(FILENAME);
        if (!file.exists()) {
            System.out.println("✗ File " + FILENAME + " does not exist!");
            System.out.println("  Please create the file first using option 1.");
            return;
        }
        
        System.out.print("How many students do you want to add? ");
        int count;
        try {
            count = Integer.parseInt(scanner.nextLine().trim());
        } catch (NumberFormatException e) {
            System.out.println("Invalid number! Using default of 1.");
            count = 1;
        }
        
        // Collect new student information
        List newStudents = new ArrayList<>();
        for (int i = 1; i <= count; i++) {
            System.out.println("\nEnter details for new Student " + i + ":");
            
            System.out.print("Name: ");
            String name = scanner.nextLine().trim();
            
            System.out.print("Roll Number: ");
            String rollNumber = scanner.nextLine().trim();
            
            System.out.print("Marks: ");
            double marks;
            try {
                marks = Double.parseDouble(scanner.nextLine().trim());
            } catch (NumberFormatException e) {
                System.out.println("Invalid marks! Using 0.0");
                marks = 0.0;
            }
            
            newStudents.add(new StudentInfo(name, rollNumber, marks));
        }
        
        // Append to file using FileWriter with append mode
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(FILENAME, true))) {
            for (StudentInfo student : newStudents) {
                writer.write(student.toFileString());
                writer.newLine();
            }
            
            System.out.println("\n✓ " + newStudents.size() + " students appended successfully!");
            
        } catch (IOException e) {
            System.err.println("✗ Error appending to file: " + e.getMessage());
        }
    }
    
    private static void searchStudent() {
        System.out.println("\n--- Search for Student ---");
        
        File file = new File(FILENAME);
        if (!file.exists()) {
            System.out.println("✗ File " + FILENAME + " does not exist!");
            return;
        }
        
        System.out.println("Search by:");
        System.out.println("1. Name");
        System.out.println("2. Roll Number");
        System.out.print("Enter choice (1 or 2): ");
        
        int searchType;
        try {
            searchType = Integer.parseInt(scanner.nextLine().trim());
        } catch (NumberFormatException e) {
            searchType = 1;
        }
        
        System.out.print("Enter search term: ");
        String searchTerm = scanner.nextLine().trim().toLowerCase();
        
        try (BufferedReader reader = new BufferedReader(new FileReader(FILENAME))) {
            String line;
            List foundStudents = new ArrayList<>();
            
            while ((line = reader.readLine()) != null) {
                // Skip comments and empty lines
                if (line.startsWith("#") || line.trim().isEmpty()) {
                    continue;
                }
                
                StudentInfo student = StudentInfo.fromFileString(line);
                if (student != null) {
                    boolean matches = false;
                    if (searchType == 1) {
                        matches = student.getName().toLowerCase().contains(searchTerm);
                    } else {
                        matches = student.getRollNumber().toLowerCase().contains(searchTerm);
                    }
                    
                    if (matches) {
                        foundStudents.add(student);
                    }
                }
            }
            
            // Display search results
            if (foundStudents.isEmpty()) {
                System.out.println("\n✗ No students found matching: " + searchTerm);
            } else {
                System.out.println("\n✓ Found " + foundStudents.size() + " student(s):");
                System.out.println("=".repeat(80));
                for (int i = 0; i < foundStudents.size(); i++) {
                    System.out.println((i + 1) + ". " + foundStudents.get(i));
                }
                System.out.println("=".repeat(80));
            }
            
        } catch (IOException e) {
            System.err.println("✗ Error searching file: " + e.getMessage());
        }
    }
    
    private static void displayStatistics() {
        System.out.println("\n--- File Statistics ---");
        
        File file = new File(FILENAME);
        if (!file.exists()) {
            System.out.println("✗ File " + FILENAME + " does not exist!");
            return;
        }
        
        try (BufferedReader reader = new BufferedReader(new FileReader(FILENAME))) {
            String line;
            List students = new ArrayList<>();
            
            while ((line = reader.readLine()) != null) {
                if (line.startsWith("#") || line.trim().isEmpty()) {
                    continue;
                }
                
                StudentInfo student = StudentInfo.fromFileString(line);
                if (student != null) {
                    students.add(student);
                }
            }
            
            if (students.isEmpty()) {
                System.out.println("✗ No valid student records found.");
                return;
            }
            
            // Calculate statistics
            double totalMarks = 0;
            double maxMarks = Double.MIN_VALUE;
            double minMarks = Double.MAX_VALUE;
            StudentInfo topStudent = null;
            StudentInfo lowStudent = null;
            
            for (StudentInfo student : students) {
                double marks = student.getMarks();
                totalMarks += marks;
                
                if (marks > maxMarks) {
                    maxMarks = marks;
                    topStudent = student;
                }
                
                if (marks < minMarks) {
                    minMarks = marks;
                    lowStudent = student;
                }
            }
            
            double averageMarks = totalMarks / students.size();
            
            // Display statistics
            System.out.println("=".repeat(80));
            System.out.printf("Total Students      : %d%n", students.size());
            System.out.printf("Average Marks       : %.2f%n", averageMarks);
            System.out.printf("Highest Marks       : %.2f%n", maxMarks);
            System.out.printf("Lowest Marks        : %.2f%n", minMarks);
            System.out.printf("Top Performer       : %s (%.2f)%n", topStudent.getName(), topStudent.getMarks());
            System.out.printf("Needs Improvement   : %s (%.2f)%n", lowStudent.getName(), lowStudent.getMarks());
            
            // Grade distribution
            int gradeA = 0, gradeB = 0, gradeC = 0, gradeD = 0, gradeF = 0;
            for (StudentInfo student : students) {
                double marks = student.getMarks();
                if (marks >= 90) gradeA++;
                else if (marks >= 80) gradeB++;
                else if (marks >= 70) gradeC++;
                else if (marks >= 60) gradeD++;
                else gradeF++;
            }
            
            System.out.println("-".repeat(40));
            System.out.println("Grade Distribution:");
            System.out.printf("A (90-100)  : %d students%n", gradeA);
            System.out.printf("B (80-89)   : %d students%n", gradeB);
            System.out.printf("C (70-79)   : %d students%n", gradeC);
            System.out.printf("D (60-69)   : %d students%n", gradeD);
            System.out.printf("F (0-59)    : %d students%n", gradeF);
            System.out.println("=".repeat(80));
            
        } catch (IOException e) {
            System.err.println("✗ Error reading file for statistics: " + e.getMessage());
        }
    }
    
    private static void backupFile() {
        System.out.println("\n--- Backup File ---");
        
        File sourceFile = new File(FILENAME);
        if (!sourceFile.exists()) {
            System.out.println("✗ File " + FILENAME + " does not exist!");
            return;
        }
        
        String backupFileName = "backup_" + System.currentTimeMillis() + "_" + FILENAME;
        File backupFile = new File(backupFileName);
        
        try (BufferedReader reader = new BufferedReader(new FileReader(sourceFile));
             BufferedWriter writer = new BufferedWriter(new FileWriter(backupFile))) {
            
            String line;
            int linesCopied = 0;
            
            while ((line = reader.readLine()) != null) {
                writer.write(line);
                writer.newLine();
                linesCopied++;
            }
            
            System.out.println("✓ File backed up successfully!");
            System.out.println("✓ Backup file: " + backupFileName);
            System.out.println("✓ Lines copied: " + linesCopied);
            System.out.println("✓ Backup size: " + backupFile.length() + " bytes");
            
        } catch (IOException e) {
            System.err.println("✗ Error creating backup: " + e.getMessage());
        }
    }
}
                
Solution Features:
  • Complete file operations: create, read, write, append
  • Menu-driven interface for easy interaction
  • Student data management with search functionality
  • File statistics and grade distribution analysis
  • Backup functionality for data safety
  • Error handling and input validation

🧪 Hands-on Lab Exercise

Lab 19: Employee Record Management System

Task: Create a comprehensive employee record management system using various I/O streams for different data operations.

Requirements:

  • Use character streams for employee text data (name, department, email)
  • Use data streams for numeric data (salary, employee ID, hire date)
  • Implement object serialization for complete employee objects
  • Create file backup and restore functionality
  • Implement CSV import/export capabilities
  • Add logging functionality using file I/O
Challenge: Implement a transaction log system that records all file operations with rollback capability in case of failures.

📚 Lecture Summary

Key I/O Concepts Covered

  • Java I/O stream hierarchy and classification
  • Byte streams (InputStream/OutputStream)
  • Character streams (Reader/Writer)
  • File class for file system operations
  • Buffered streams for performance
  • Object serialization/deserialization

Best Practices

  • Use try-with-resources for automatic stream closure
  • Choose appropriate stream type for data
  • Use buffered streams for better performance
  • Handle IOException properly
  • Use character streams for text data
  • Implement Serializable for object persistence

🎯 Next Lecture Preview

Lecture 20: Lambda Expressions and Functional Interfaces

  • Functional programming concepts in Java
  • Lambda expression syntax and usage
  • Built-in functional interfaces
  • Stream API and functional operations