Introduction to Java I/O (Input/Output)

Java I/O (Input/Output) is a fundamental aspect of Java programming that deals with reading and writing data to and from various sources, such as files, network connections, and other input or output devices. Java provides a comprehensive set of classes and interfaces under the java.io package to perform these operations. The primary purpose of Java I/O is to facilitate the transfer of data efficiently and conveniently.

Five Categories of I/O Streams

Java I/O streams are categorized into five main types based on the type of data they handle and their functionality:

1. Byte Streams

Description: Byte streams handle the I/O of raw binary data. They are suitable for handling all kinds of data, including images, audio, and other binary files.

Classes:

  • InputStream
  • OutputStream

Common subclasses:

  • FileInputStream
  • FileOutputStream
  • BufferedInputStream
  • BufferedOutputStream

Example:

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

public class ByteStreamExample {
    public static void main(String[] args) {
        try (FileInputStream in = new FileInputStream("input.txt");
             FileOutputStream out = new FileOutputStream("output.txt")) {
            int byteData;
            while ((byteData = in.read()) != -1) {
                out.write(byteData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2. Character Streams

Description: Character streams handle the I/O of character data, automatically handling the translation to and from the local character set. They are ideal for text data.

Classes:

  • Reader
  • Writer

Common subclasses:

  • FileReader
  • FileWriter
  • BufferedReader
  • BufferedWriter

Example:

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

public class CharacterStreamExample {
    public static void main(String[] args) {
        try (FileReader reader = new FileReader("input.txt");
             FileWriter writer = new FileWriter("output.txt")) {
            int charData;
            while ((charData = reader.read()) != -1) {
                writer.write(charData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. Buffered Streams

Description: Buffered streams optimize input and output operations by reducing the number of calls to the native API. They use an internal buffer to read and write data in chunks, improving performance.

Classes:

  • BufferedInputStream
  • BufferedOutputStream
  • BufferedReader
  • BufferedWriter

Example:

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

public class BufferedStreamExample {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"));
             BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                writer.write(line);
                writer.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4. Data Streams

Description: Data streams handle the binary I/O of primitive data types and String values. They allow reading and writing of Java primitive data types in a machine-independent way.

Classes:

  • DataInputStream
  • DataOutputStream

Example:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class DataStreamExample {
    public static void main(String[] args) {
        try (DataOutputStream out = new DataOutputStream(new FileOutputStream("data.dat"));
             DataInputStream in = new DataInputStream(new FileInputStream("data.dat"))) {
            out.writeInt(123);
            out.writeDouble(45.67);
            out.writeUTF("Hello, world!");

            int intValue = in.readInt();
            double doubleValue = in.readDouble();
            String strValue = in.readUTF();

            System.out.println("Int: " + intValue);
            System.out.println("Double: " + doubleValue);
            System.out.println("String: " + strValue);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5. Object Streams

Description: Object streams handle the binary I/O of objects. They allow reading and writing of entire objects, enabling object serialization and deserialization.

Classes:

  • ObjectInputStream
  • ObjectOutputStream

Example:

import java.io.*;

class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

public class ObjectStreamExample {
    public static void main(String[] args) {
        Person person = new Person("John Doe", 30);

        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("person.ser"));
             ObjectInputStream in = new ObjectInputStream(new FileInputStream("person.ser"))) {
            out.writeObject(person);

            Person deserializedPerson = (Person) in.readObject();
            System.out.println("Deserialized Person: " + deserializedPerson);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Conclusion

Java I/O is a crucial part of Java programming, providing various streams to handle different types of data. The five categories of I/O streams—Byte Streams, Character Streams, Buffered Streams, Data Streams, and Object Streams—offer versatile and efficient ways to perform input and output operations, catering to a wide range of use cases. Understanding these streams and their functionalities helps in choosing the right approach for specific data handling needs in Java applications.

Comments