Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java file channels: buffer positions and partial transfers

Last updated: 29 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

FileChannel moves bytes between a file and buffers whose positions and limits describe the next readable or writable region.

Java 8+. This is a complete program using JDK classes.

Move the buffer between modes

A manifest header uses three four-byte signed integers in big-endian order. putInt advances the position as the header is built. flip sets the limit to the written extent and resets the position so the next operation reads those bytes for output.

A write call can transfer fewer bytes than requested. Loop while the buffer has remaining data. Reading back has the same partial-transfer boundary; stop on end-of-file and reject a truncated header rather than parsing an incomplete buffer.

Byte order belongs to the file format. ByteBuffer has a default, but stating the order beside the field layout prevents a future implementation in another language from guessing. Direct buffers, mapped regions and zero-copy transfers have separate lifetime and platform tradeoffs; this small header does not need them.

Own the file and the channel

The fixture creates a temporary file and removes it after channel closure. It also checks the exact number of header bytes read. Successful write completion does not promise crash durability; a persistent application needs a force and replacement policy appropriate to its filesystem.

Working program

Java
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.file.*;
public class ManifestHeaderChannel {
    public static void main(String[] args) throws Exception {
        Path file = Files.createTempFile("aitrove-header-", ".bin");
        try {
            ByteBuffer header = ByteBuffer.allocate(12).order(ByteOrder.BIG_ENDIAN);
            header.putInt(7).putInt(42).putInt(3).flip();
            try (FileChannel channel = FileChannel.open(file, StandardOpenOption.WRITE, StandardOpenOption.READ)) {
                while (header.hasRemaining()) channel.write(header);
                channel.position(0);
                ByteBuffer restored = ByteBuffer.allocate(12).order(ByteOrder.BIG_ENDIAN);
                while (restored.hasRemaining() && channel.read(restored) != -1) { }
                if (restored.position() != 12) throw new IllegalStateException("Truncated header");
                restored.flip();
                System.out.println(restored.getInt() + ":" + restored.getInt() + ":" + restored.getInt());
            }
        } finally { Files.deleteIfExists(file); }
    }
}

Output

Output
7:42:3

Costs and boundaries

This fixed header holds 12 bytes, so its application buffer is O(1). General file copying visits O(n) bytes and needs a bounded chunk buffer. Storage latency and partial transfers make the number of system calls different from the number of fields in the format.

Common Mistakes

  • Reading a freshly filled buffer requires changing its position and limit.
  • One read is not a complete-record guarantee.
  • A closed channel does not imply a crash-durable transaction.

Read next

Stream transfer loops, File paths and ownership.

Extend the tested workflow

Continue with Java ByteBuffer byte order: decode the protocol before reading integers, Java CRC32: detect a byte change without claiming authenticity.

java
file-channels
Storage details