---
title: "I/O, NIO, files, and serialization"
chapter: "11"
---

# I/O, NIO, files, and serialization

I/O crosses an application boundary and therefore needs limits, cleanup, and
validation.

## Bytes and characters

Input/output streams work with bytes. Readers/writers work with characters and
need a charset. Specify UTF-8 or the protocol charset; do not rely on platform
defaults for persistent data.

Buffering reduces expensive small system calls. `Files` and `Path` provide
modern file operations. Many directory and line streams are lazy resources
that must be closed.

## NIO

NIO includes paths, channels, buffers, selectors, asynchronous channels, and
memory-mapped files. A `ByteBuffer` has capacity, position, and limit. `flip`
changes from writing data into the buffer to reading it out.

## Safe file processing

Validate file size and type, avoid following unexpected symbolic links, prevent
path traversal, write to a temporary file, sync when durability requires it,
and atomically move into place where supported. Limit decompression to prevent
zip bombs.

## Object serialization

Native Java serialization has long-term compatibility and security risks.
Do not deserialize untrusted data. Prefer explicit formats such as JSON,
Protocol Buffers, or a well-designed binary contract. If legacy serialization
is unavoidable, apply serialization filters and strict type boundaries.

## HTTP client

The JDK `HttpClient` supports HTTP/1.1, HTTP/2, synchronous and asynchronous
calls. Reuse clients, set connect/request timeouts, bound body sizes, validate
TLS and redirects, and handle interruption.

## Feynman check

Bytes are sealed packages; a charset is the translation guide that turns
packages into letters. A buffer is a tray with a marker showing where writing
or reading happens next.
