Java I/O (Input/Output) is a crucial part of Java programming for handling file operations and data exchange. Here’s an overview of the key components in Java I/O, including file handling, byte and character streams, buffered streams, data streams, and object serialization.

1. File Handling

Java provides several classes for file handling, primarily in the java.ioand java.nio.file packages. The most commonly used class is File for file operations.

Basic File Operations:

  • Creating a File:
  import java.io.File;
import java.io.IOException;

public class FileExample {
    public static void main(String[] args) {
        File file = new File("example.txt");
        try {
            if (file.createNewFile()) {
                System.out.println("File created: " + file.getName());
            } else {
                System.out.println("File already exists.");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  

Deleting a File:

  File file = new File("example.txt");
if (file.delete()) {
    System.out.println("Deleted the file: " + file.getName());
} else {
    System.out.println("Failed to delete the file.");
}
  

Checking File Properties:

  File file = new File("example.txt");
if (file.exists()) {
    System.out.println("File size: " + file.length() + " bytes");
}
  

2. Byte Streams

Byte streams read and write data in bytes and are suitable for binary data such as image files or audio files.

  • InputStream: Reads bytes from a file or other input source.
  import java.io.FileInputStream;
import java.io.IOException;

public class ByteStreamExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("example.bin")) {
            int byteData;
            while ((byteData = fis.read()) != -1) {
                System.out.print((char) byteData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  
  • OutputStream: Writes bytes to a file or other output destination.
  import java.io.FileOutputStream;
import java.io.IOException;

public class ByteStreamExample {
    public static void main(String[] args) {
        try (FileOutputStream fos = new FileOutputStream("example.bin")) {
            String data = "Hello, World!";
            fos.write(data.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  

3. Character Streams

Character streams read and write data in characters and are suitable for text files.

  • Reader: Reads characters from a file or other input source.
  import java.io.FileReader;
import java.io.IOException;

public class CharacterStreamExample {
    public static void main(String[] args) {
        try (FileReader fr = new FileReader("example.txt")) {
            int charData;
            while ((charData = fr.read()) != -1) {
                System.out.print((char) charData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  

Writer: Writes characters to a file or other output destination.

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

public class CharacterStreamExample {
    public static void main(String[] args) {
        try (FileWriter fw = new FileWriter("example.txt")) {
            String data = "Hello, World!";
            fw.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  

4. Buffered Streams

Buffered streams provide efficient reading and writing by reducing the number of I/O operations.

  • BufferedInputStream:
  import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class BufferedStreamExample {
    public static void main(String[] args) {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("example.bin"))) {
            int byteData;
            while ((byteData = bis.read()) != -1) {
                System.out.print((char) byteData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  
  • BufferedOutputStream:
  import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedStreamExample {
    public static void main(String[] args) {
        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("example.bin"))) {
            String data = "Hello, World!";
            bos.write(data.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  

5. Data Streams

Data streams provide methods for reading and writing Java primitive data types.

  • DataInputStream:
  import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class DataStreamExample {
    public static void main(String[] args) {
        try (DataInputStream dis = new DataInputStream(new FileInputStream("example.dat"))) {
            int intData = dis.readInt();
            double doubleData = dis.readDouble();
            System.out.println("Integer: " + intData);
            System.out.println("Double: " + doubleData);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  
  • DataOutputStream:
  import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class DataStreamExample {
    public static void main(String[] args) {
        try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("example.dat"))) {
            dos.writeInt(123);
            dos.writeDouble(456.78);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  

6. Object Serialization and Deserialization

Serialization is the process of converting an object into a byte stream, and deserialization is the reverse process.

  • Serialization:
  import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class SerializationExample {
    public static void main(String[] args) {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.ser"))) {
            MyObject obj = new MyObject("Hello", 123);
            oos.writeObject(obj);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class MyObject implements Serializable {
    private static final long serialVersionUID = 1L;
    private String message;
    private int number;

    public MyObject(String message, int number) {
        this.message = message;
        this.number = number;
    }

    @Override
    public String toString() {
        return "MyObject{message='" + message + "', number=" + number + '}';
    }
}
  
  • Deserialization:
  import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;

public class DeserializationExample {
    public static void main(String[] args) {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.ser"))) {
            MyObject obj = (MyObject) ois.readObject();
            System.out.println("Deserialized object: " + obj);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class MyObject implements Serializable {
    private static final long serialVersionUID = 1L;
    private String message;
    private int number;

    public MyObject(String message, int number) {
        this.message = message;
        this.number = number;
    }

    @Override
    public String toString() {
        return "MyObject{message='" + message + "', number=" + number + '}';
    }
}
  

Summary

  • File Handling: Use File class for basic file operations.
  • Byte Streams: Use InputStream and OutputStream for binary data.
  • Character Streams: Use Reader and Writer for text data.
  • Buffered Streams: Use BufferedInputStream and BufferedOutputStream for efficient I/O.
  • Data Streams: Use DataInputStream and DataOutputStream for reading and writing Java primitive data types.
  • Serialization/Deserialization: Use ObjectInputStream and ObjectOutputStream for converting objects to/from byte streams.