A FileChannel.write call advances a ByteBuffer by the number of bytes it actually wrote. A caller that needs the entire payload must loop until the buffer has no remaining bytes.
Java FileChannel.write: finish the buffer before reporting success
Operational contract
The channel is opened with CREATE_NEW so an existing manifest cannot be overwritten by this helper. The buffer wraps bytes already owned by the caller; the caller must not mutate that array during the write. A zero-byte write is treated as lack of progress rather than an excuse to spin forever. Closing the channel releases its handle but is not the same as an explicit durability request. If the write fails halfway, a partial new file may remain; the caller owns cleanup or should stage to a temporary name before publication.
Failure case
A receipt batch is encoded into 47,000 bytes. One write returns after 16,384 bytes. Treating that return as completion publishes a truncated batch. The loop continues from the buffer's new position and only returns after all bytes have been accepted by the channel. It still does not claim that the data survived a power failure.
Java code
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
public class ManifestChannelWriter {
public static void create(Path destination, byte[] payload) throws IOException {
try (FileChannel channel = FileChannel.open(destination,
StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)) {
ByteBuffer pending = ByteBuffer.wrap(payload);
while (pending.hasRemaining()) {
if (channel.write(pending) == 0) throw new IOException("Channel made no write progress");
}
}
}
}Performance and ownership cost
The loop writes B bytes in O(B) I/O work and uses O(1) extra application storage because ByteBuffer wraps the caller's array. Device and filesystem costs dominate. A staged publish adds another file operation but prevents readers from opening a half-written final name.
Common Mistakes
- Do not assume one write drains a ByteBuffer.
- Do not mutate the wrapped byte array during the write.
- Do not call close alone a full durability or publication guarantee.
Connected lessons
- Java ByteBuffer flip and compact: preserve an incomplete frame
- Java Files.move: atomic publication is a filesystem contract
- Java file I/O: UTF-8, streaming reads, and path ownership
- Java positioned FileChannel.read: detect a short record without moving the cursor
- Java FileChannel.transferTo: verify the byte count on every pass
- Java FileChannel.force: distinguish written bytes from forced storage
- Java FileLock: coordinate one byte range with a shared protocol
- Java FileChannel.truncate: cut only after validating the recovery offset
- Java AsynchronousFileChannel: own the buffer through completion
- Java file channels and JVM observations quiz
- Advanced Java
