Understanding Java I/O Streams: A Comprehensive Guide

1. What Are I/O Streams?

I stands for Input, and O stands for Output. These streams handle reading and writing of data to files or other sources.

2. I/O Classification

Classification by Data Processing Format
  • Byte Streams: Handle binary data (images, audio, video, etc.)
    • InputStream: Byte-based input stream
    • OutputStream: Byte-based output stream
  • Character Streams: Handle character data (text files, etc.)
    • Reader: Character-based input stream
    • Writer: Character-based output stream
Classification by Data Flow Direction
  • Input streams
  • Output streams

Note: How to determine whether to use input or output stream?
Using the program as reference, observe the data flow direction. If data flows into the program, use input stream. If data flows out of the program, use output stream.

3. Byte Streams

3.1 Byte Input Streams
  • InputStream: Abstract class
    • FileInputStream: File operations (important)
    • BufferedInputStream: Buffered byte stream (reference only)
Common InputStream Methods
  • int read(): Read single byte (low efficiency)
  • int read(byte[] buffer): Read multiple bytes (improved efficiency)
  • int read(byte[] buffer, int offset, int length)
  • void close(): Close stream
FileInputStream File Reading Steps
  1. Locate the target file (specify path)
  2. Establish data channel with target file (create stream)
  3. Read file data using read()
  4. Close channel (release resources)
BufferedInputStream File Reading Steps
  1. Locate the target file (specify path)
  2. Establish data channel with target file
  3. Create buffered data channel
  4. Read data using buffered stream
  5. Close buffered channel (release resources)
public static void main(String[] args) {
    String filePath = "C:\\Users\\User\\Desktop\\sample.txt";
    FileInputStream inputStream = null;

    try {
        inputStream = new FileInputStream(filePath);
        int byteData;
        while ((byteData = inputStream.read()) != -1) {
            System.out.print((char) byteData);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (inputStream != null) {
                inputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

FileNotFoundException: Thrown when file cannot be located.

Important: Reading character data using byte streams may result in garbled text.

String filePath = "C:\\Users\\User\\Desktop\\sample.txt";
FileInputStream inputStream = null;
try {
    inputStream = new FileInputStream(filePath);
    byte[] buffer = new byte[1024 * 8];
    int bytesRead;
    while ((bytesRead = inputStream.read(buffer)) != -1) {
        System.out.println(Arrays.toString(buffer));
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if (inputStream != null) {
            inputStream.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}
// Buffered byte input stream (for reference only)
// Note: Buffered streams cannot read/write independently, they depend on streams
public static void main(String[] args) {
    long startTime = System.currentTimeMillis();
    String targetPath = "C:\\data\\input.dat";
    FileInputStream fileStream = null;
    BufferedInputStream bufferedStream = null;
    
    try {
        fileStream = new FileInputStream(targetPath);
        bufferedStream = new BufferedInputStream(fileStream);
        byte[] dataBuffer = new byte[1024 * 8];
        int totalBytes = 0;
        while ((totalBytes = bufferedStream.read(dataBuffer)) != -1) {
            System.out.println(Arrays.toString(dataBuffer));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (fileStream != null) {
                fileStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
3.2 Byte Output Streams
  • OutputStream: Abstract class
    • FileOutputStream
Common FileOutputStream Methods
  • write(int b): Write single byte
  • write(byte[] buffer): Write multiple bytes
  • write(byte[] buffer, int offset, int length)
  • close(): Close stream
Steps to Write Data
  1. Locate target file
  2. Establish data channel
  3. Write data using channel
  4. Close channel
public static void writeDataToFile() {
    String outputPath = "C:\\Users\\User\\Desktop\\output.txt";
    FileOutputStream outputStream = null;
    try {
        outputStream = new FileOutputStream(outputPath, true); // true: append; false: overwrite (default)
        outputStream.write("hello world".getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (outputStream != null) {
                outputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Note: Stream refers to byte/binary data. Input means entering, Output means exiting. Buffered means using memory caching.

3.3 Image Copying: Read and Write Simultaneously
write(byte[] buffer, int offset, int length)
    buffer: array to write from
    offset: starting position in array (typically 0)
    length: number of bytes to write

Note: When writing character data using byte streams, manual encoding is required.

4. Character Streams

Character streams handle character reading and writing. Character streams combine byte streams with encoding/decoding operations, allowing direct character writing.

Encoding: Converting readable characters in to unreadable binary data.

Decoding: Converting unreadable binary data back into readable characters.

4.1 Reading Data
  • Reader
    • FileReader
    • BufferedReader
      • String readLine(): Reads one line at a time. Note: Does not include newline characters.
public static void main(String[] args) throws Exception {
    FileReader fileReader = new FileReader("C:\\data\\text.txt");
    int character;
    while ((character = fileReader.read()) != -1) {
        System.out.println((char) character);
    }
    fileReader.close();
}
Using Buffered Array (Higher Efficiency)
public static void main(String[] args) throws Exception {
    FileReader fileReader = new FileReader("C:\\data\\text.txt");
    char[] charBuffer = new char[1024 * 8];
    int charsRead;
    while ((charsRead = fileReader.read(charBuffer)) != -1) {
        System.out.println(new String(charBuffer, 0, charsRead));
    }
    fileReader.close();
}
// Reading with BufferedReader
// Note: BufferedReader cannot read/write directly without an underlying stream
public static void main(String[] args) throws Exception {
    FileReader baseReader = new FileReader("C:\\data\\text.txt");
    BufferedReader bufReader = new BufferedReader(baseReader);
    String lineContent;
    while ((lineContent = bufReader.readLine()) != null) {
        System.out.println(lineContent + "\r\n");
    }
    bufReader.close();
    baseReader.close();
}
4.2 Writing Data
  • Writer
    • FileWriter
    • BufferedWriter
// Writing without BufferedWriter
public static void main(String[] args) throws Exception {
    FileWriter fileWriter = new FileWriter("C:\\data\\output.txt");
    fileWriter.write("hello world,你好!");
    fileWriter.close();
}
// Writing with BufferedWriter
public static void main(String[] args) throws Exception {
    FileWriter baseWriter = new FileWriter("C:\\data\\output.txt");
    BufferedWriter bufWriter = new BufferedWriter(baseWriter);
    bufWriter.write("hello world,你好!");
    bufWriter.close();
    baseWriter.close();
}
4.3 File Copying
public static void main(String[] args) throws Exception {
    BufferedReader reader = new BufferedReader(new FileReader("C:\\source.txt"));
    BufferedWriter writer = new BufferedWriter(new FileWriter("C:\\destination.txt"));
    
    String lineData;
    while ((lineData = reader.readLine()) != null) {
        writer.write(lineData);
        writer.newLine(); // New line approach
    }
    reader.close();
    writer.close();
}

5. Conversion Streams

Conversion streams transform byte streams into character streams.

5.1 Converting Input Byte Stream to Character Stream
public static void main(String[] args) throws Exception {
    FileInputStream byteStream = new FileInputStream("C:\\data\\input.txt");
    InputStreamReader charStream = new InputStreamReader(byteStream);
    char[] buffer = new char[1024 * 8];
    int charsRead;
    while ((charsRead = charStream.read(buffer)) != -1) {
        System.out.println(new String(buffer, 0, charsRead));
    }
    charStream.close();
}
5.2 Converting Output Byte Stream to Character Stream
public static void main(String[] args) throws Exception {
    FileOutputStream byteStream = new FileOutputStream("C:\\data\\output.txt");
    OutputStreamWriter charStream = new OutputStreamWriter(byteStream);
    charStream.write("hello world");
    charStream.close();
}

6. Object Streams

Object streams handle reading and writing Java objects.

Serialization: Converting Java objects into storable/transmittable format.

Deserialization: Reconstructing Java objects from stored/transmitted format.

public class Student implements Serializable {
    private static final long serialVersionUID = 1L;
    private int studentId;
    private String studentName;
    private String gender;
}
6.1 Writing Java Objects to File (Serialization)
public static void serializeStudent() throws Exception {
    Student student = new Student();
    student.setStudentId(120);
    student.setStudentName("John");
    student.setGender("Male");
    
    FileOutputStream fileOut = new FileOutputStream("student.dat");
    ObjectOutputStream objOut = new ObjectOutputStream(fileOut);
    objOut.writeObject(student);
    objOut.close();
    fileOut.close();
}
6.2 Reading Java Objects from File (Deserialization)
public static void deserializeStudent() throws Exception {
    FileInputStream fileIn = new FileInputStream("student.dat");
    ObjectInputStream objIn = new ObjectInputStream(fileIn);
    Student restoredStudent = (Student) objIn.readObject();
    objIn.close();
    fileIn.close();
}

Important: Does object creation call the constructor during deserialization?
Deserialization does NOT invoke the constructor.

Problem: Deserialization fails after modifying class members.
Solution: The serialVersionUID is computed from the class structure. When class changes occur, this UID changes. Solutions:

  1. Reserialize the object
  2. Define serialVersionUID explicitly in the entity class
private static final long serialVersionUID = 1L;

7. File Class

The File class encapsulates file and directory operations.

7.1 Constructors
// Constructor 1: File(String pathname)
public static void constructorDemo1() {
    File fileObj = new File("C:\\data\\sample.txt");
}

// Constructor 2: File(String parent, String child)
public static void constructorDemo2() {
    File fileObj = new File("C:\\data", "sample.txt");
}

// Constructor 3: File(File parent, String child)
public static void constructorDemo3() {
    File parentDir = new File("C:\\data");
    File fileObj = new File(parentDir, "sample.txt");
}
7.2 Common Methods
File targetFile = new File("C:\\data\\test.txt");
System.out.println("Exists: " + targetFile.exists());
System.out.println("Is file: " + targetFile.isFile());
System.out.println("Is directory: " + targetFile.isDirectory());

if (!targetFile.exists()) {
    if (targetFile.isFile()) {
        targetFile.createNewFile();
    }
    String fileName = targetFile.getName();
    String parentPath = targetFile.getParent();
    String fullPath = targetFile.getPath();
}
Creating Directories
public static void createDirectories() {
    File dir1 = new File("C:\\testdir");
    if (!dir1.exists()) {
        dir1.mkdir(); // Creates single-level directory
    }
    
    File dir2 = new File("C:\\testdir\\subdir");
    if (!dir2.exists()) {
        dir2.mkdirs(); // Creates multi-level directories
    }
}
Retrieving All Files
public static void listAllFiles() {
    File directory = new File("C:\\data");
    String[] fileList = directory.list();
    for (String name : fileList) {
        System.out.println(name);
    }
}
// Get all file objects: File[] listFiles()
File directory = new File("C:\\data");
File[] files = directory.listFiles();
for (File f : files) {
    System.out.println(f);
}
// Filter files using FilenameFilter
String[] javaFiles = directory.list(new FilenameFilter() {
    public boolean accept(File dir, String name) {
        return name.endsWith(".java");
    }
});

// Filter image files using FileFilter
File[] imageFiles = directory.listFiles(new FilenameFilter() {
    public boolean accept(File dir, String name) {
        return name.endsWith(".png") || name.endsWith(".jpg");
    }
});
Deleting Files and Directories
public static void deleteOperations() {
    File fileToDelete = new File("C:\\data\\temp.txt");
    fileToDelete.delete(); // Deletes file or empty directory
    
    File dirToDelete = new File("C:\\tempdir");
    dirToDelete.delete(); // Only deletes empty directories
}
Using File Class with I/O Streams
public static void fileIoDemo() {
    File targetFile = new File("C:\\data\\document.txt");
    FileReader reader = new FileReader(targetFile);
    char[] buffer = new char[1024 * 8];
    int bytesRead;
    while ((bytesRead = reader.read(buffer)) != -1) {
        System.out.println(new String(buffer, 0, bytesRead));
    }
    reader.close();
}

Tags: java io-streams InputStream OutputStream filereader

Posted on Sat, 07 Nov 2026 16:27:41 +0000 by Misticx