Master Java I/O: Streams, NIO, and Serialization Explained
This article introduces Java I/O streams, explains how to efficiently read large files using buffered streams and NIO, details the core components of Java NIO (Channel, Buffer, Selector), and covers object serialization, the role of serialVersionUID, and alternative serialization frameworks.
1. Introduction to Java I/O Streams
IO (Input Output) is used for data input and output. Java abstracts various sources (keyboard, file, network) as streams, which are ordered data from source to destination, allowing uniform access.
Based on data direction, streams are input (read‑only) or output (write‑only).
Based on data type, streams are byte streams (8‑bit) or character streams (16‑bit).
Based on functionality, streams are node (low‑level) streams that directly read/write devices, or processing (high‑level) streams that wrap node streams to simplify or improve efficiency.
Java provides many classes for I/O; abstract base classes are shown in black, node streams in red, processing streams in blue.
Naming conventions indicate purpose:
File* streams access files.
ByteArray*/CharArray* streams access memory arrays.
Piped* streams implement pipes for inter‑process communication.
String* streams work with strings in memory.
Buffered* streams add buffering to reduce I/O operations.
InputStreamReader / OutputStreamWriter are conversion streams between byte and character streams.
Object* streams handle object serialization.
Print* streams simplify printing.
Pushback* streams allow unread data to be pushed back into the buffer.
Data* streams read/write Java primitive types.
2. How to Open a Large File with Streams
To avoid loading an entire file into memory, read it in chunks.
Use buffered streams, which maintain an internal buffer to reduce device interactions. Reads fill the buffer; subsequent reads come from the buffer until it empties.
Use NIO with memory‑mapped files, allowing the file (or a region) to be mapped into memory for fast access, similar to virtual memory.
3. How NIO Works
Java NIO consists of three core components: Channel, Buffer, Selector.
All I/O starts with a Channel; data moves between Channel and Buffer. Common channel types include FileChannel, DatagramChannel, SocketChannel, ServerSocketChannel.
A Buffer is a memory block that can be written to and read from. NIO provides buffers for all primitive types (ByteBuffer, CharBuffer, etc.).
Buffers have three key properties: capacity (fixed maximum size), position (current index), and limit (boundary for read/write). Their meanings depend on whether the buffer is in read or write mode.
capacity: maximum number of elements the buffer can hold.
position: index of the next element to read or write.
limit: in write mode, the maximum index that can be written (often equals capacity); in read mode, the index of the first element not yet read (set to position when switching to read mode).
The Selector enables a single thread to monitor multiple Channels. Channels are registered with the Selector, which blocks on select() until an event occurs, then the thread processes the ready events.
4. Java Serialization and Deserialization
Serialization converts an object into a byte sequence that can be stored or transmitted; deserialization restores the object from that byte sequence. A class must implement the marker interface Serializable to be eligible.
ObjectOutputStream.writeObject() writes an object; ObjectInputStream.readObject() reads it back.
5. Why Define serialVersionUID?
serialVersionUID identifies the version of a serialized class. During deserialization, the stored UID must match the current class UID; otherwise, an InvalidClassException is thrown, preventing incompatibility issues.
Without a defined UID, changes to the class (adding/removing fields) can cause deserialization failures.
6. Alternative Serialization Tools
JSON libraries (Jackson, Gson, Fastjson) – human‑readable, but slower than binary formats.
Protobuf – language‑agnostic binary format, compact and fast.
Thrift – high‑performance RPC framework with its own serialization.
Avro – supports JSON or binary formats, schema evolution, suited for big‑data pipelines.
7. Serializing Without JSON Libraries
Use Java’s built‑in serialization (lower performance, suitable for small projects) or third‑party libraries such as Protobuf, Thrift, Avro.
Java Interview Crash Guide
Dedicated to sharing Java interview Q&A; follow and reply "java" to receive a free premium Java interview guide.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
