Fundamentals 16 min read

Master Java IO Streams: Byte, Character, and Object Streams Explained

This article provides a comprehensive guide to Java I/O streams, covering the distinction between node (low‑level) and processing (high‑level) streams, byte versus character streams, their superclasses, common implementations, buffering techniques, object serialization, and practical code examples for reading and writing data.

Java One
Java One
Java One
Master Java IO Streams: Byte, Character, and Object Streams Explained

1. Byte Streams

Java I/O treats data as streams of bytes. The abstract superclasses InputStream and OutputStream define the basic read/write contracts.

InputStream : int read() reads a single byte (returns -1 at end of stream); int read(byte[] b) reads up to b.length bytes and returns the actual count.

OutputStream : void write(int b) writes the low‑order eight bits of an int; void write(byte[] b) writes the whole array; void write(byte[] b, int off, int len) writes a sub‑range.

1.1 FileOutputStream

package com.imango.io.bytebase;

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

public class MyFileOutputStream {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("file-stream.txt");
        fos.write(1); // write byte value 1
        fos.write(2); // write byte value 2
        fos.close();
    }
}

1.2 FileInputStream

package com.imango.io.bytebase;

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

public class MyFileInputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("file-stream.txt");
        int d = fis.read(); // 1
        System.out.println(d);
        d = fis.read(); // 2
        System.out.println(d);
        d = fis.read(); // -1 (EOF)
        System.out.println(d);
        fis.close();
    }
}

1.3 Buffered Byte Streams

BufferedOutputStream and BufferedInputStream wrap a low‑level stream and use an internal 8 KB buffer to reduce native I/O calls, improving throughput.

Tip: Use buffered streams when reading or writing large amounts of data to minimize system calls.

2. Character Streams

Character streams operate on char units. The abstract superclasses Reader and Writer handle conversion between bytes and characters automatically.

2.1 Conversion Streams

InputStreamReader and OutputStreamWriter bridge byte streams and character streams, allowing text processing while the underlying I/O remains byte‑based.

2.1.1 OutputStreamWriter Example

package com.imango.io.charbase;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;

public class MyOutputStreamWriter {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("file-stream.txt");
        OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
        osw.write("今天天气真好!");
        osw.write("我们准备出去旅游");
        osw.write("写出完毕!");
        osw.close();
    }
}

2.1.2 InputStreamReader Example

package com.imango.io.charbase;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

public class MyInputStreamReader {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("file-stream.txt");
        InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
        int d;
        while ((d = isr.read()) != -1) {
            System.out.println((char) d);
        }
        isr.close();
    }
}

2.2 Buffered Character Streams

BufferedWriter , PrintWriter and BufferedReader add a default 8 KB character buffer, enabling block I/O and convenient line‑oriented methods.

2.2.1 BufferedWriter and PrintWriter

package com.imango.io.charbuffered;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

public class MyBufferedWriter {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("file-stream.txt");
        OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
        BufferedWriter bw = new BufferedWriter(osw);
        PrintWriter pw = new PrintWriter(bw, true); // auto‑flush on newline
        Scanner scanner = new Scanner(System.in);
        while (true) {
            String line = scanner.nextLine();
            if ("exit".equalsIgnoreCase(line)) {
                break;
            }
            pw.println(line);
        }
        pw.close();
    }
}

2.2.2 BufferedReader

package com.imango.io.charbuffered;

import java.io.*;

public class MyBufferedReader {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("file-stream.txt");
        InputStreamReader isr = new InputStreamReader(fis);
        BufferedReader br = new BufferedReader(isr);
        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        br.close();
    }
}

2.3 Object Streams and Serialization

ObjectOutputStream and ObjectInputStream serialize Java objects to a byte sequence and deserialize them back. The target class must implement java.io.Serializable; otherwise a NotSerializableException is thrown.

package com.imango.io.byteobject;

import com.imango.io.Person;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class MyObjectOutputStream {
    public static void main(String[] args) throws IOException {
        Person p = new Person("Tony", 18, "女", new String[]{"是一名大学生", "来自中国", "爱好唱歌"});
        FileOutputStream fos = new FileOutputStream("person.obj");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(p);
        oos.close();
    }
}
package com.imango.io.byteobject;

import com.imango.io.Person;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class MyObjectInputStream {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileInputStream fis = new FileInputStream("person.obj");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Person p = (Person) ois.readObject();
        System.out.println(p);
        ois.close();
    }
}

3. Summary of Common Java Streams

Low‑level (node) streams: FileInputStream, FileOutputStream, etc.

High‑level (processing) streams: buffered streams, conversion streams, object streams.

Categories: byte streams, character streams, object streams.

Buffered streams improve I/O efficiency by reducing system calls.

Conversion streams connect byte‑based and character‑based APIs.

Object streams enable serialization of objects that implement Serializable.

JavaserializationStreamsIOObjectStreamByteStreamCharacterStream
Java One
Written by

Java One

Sharing common backend development knowledge.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.