/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package java.nio.channels; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.spi.AbstractInterruptibleChannel; /** * An abstract channel type for interaction with a platform file. * <p> * A {@code FileChannel} defines the methods for reading, writing, memory * mapping, and manipulating the logical state of a platform file. This type * does not have a method for opening files, since this behavior has been * delegated to the {@link java.io.FileInputStream}, * {@link java.io.FileOutputStream} and {@link java.io.RandomAccessFile} types. * <p> * FileChannels created from a {@code FileInputStream} or a * {@code RandomAccessFile} created in mode "r", are read-only. FileChannels * created from a {@code FileOutputStream} are write-only. FileChannels created * from a {@code RandomAccessFile} created in mode "rw" are read/write. * FileChannels created from a {@code RandomAccessFile} that was opened in * append-mode will also be in append-mode -- meaning that each write will be * proceeded by a seek to the end of file. * <p> * FileChannels have a virtual pointer into the file which is referred to as a * file <em>position</em>. The position can be manipulated by moving it * within the file, and the current position can be queried. * <p> * FileChannels also have an associated <em>size</em>. The size of the file * is the number of bytes that it currently contains. The size can be * manipulated by adding more bytes to the end of the file (which increases the * size) or truncating the file (which decreases the size). The current size can * also be queried. * <p> * FileChannels have operations beyond the simple read, write, and close. They * can also: * <ul> * <li>request that cached data be forced onto the disk,</li> * <li>lock ranges of bytes associated with the file,</li> * <li>transfer data directly to another channel in a manner that has the * potential to be optimized by the platform,</li> * <li>memory-mapping files into NIO buffers to provide efficient manipulation * of file data,</li> * <li>read and write to the file at absolute byte offsets in a fashion that * does not modify the current position.</li> * </ul> * <p> * FileChannels are thread-safe. Only one operation involving manipulation of * the file position may be executed at the same time. Subsequent calls to such * operations will block, and one of those blocked will be freed to continue * when the first operation has completed. There is no ordered queue or fairness * applied to the blocked threads. * <p> * It is undefined whether operations that do not manipulate the file position * will also block when there are any other operations in-flight. * <p> * The logical view of the underlying file is consistent across all FileChannels * and I/O streams opened on the same file by the same VM. * Therefore, modifications performed via a channel will be visible to the * stream and vice versa; this includes modifications to the file position, * content, size, etc. */ public abstract class FileChannel extends AbstractInterruptibleChannel implements GatheringByteChannel, ScatteringByteChannel, ByteChannel { /** * {@code MapMode} defines file mapping mode constants. */ public static class MapMode { /** * Private mapping mode (equivalent to copy on write). */ public static final MapMode PRIVATE = new MapMode("PRIVATE"); /** * Read-only mapping mode. */ public static final MapMode READ_ONLY = new MapMode("READ_ONLY"); /** * Read-write mapping mode. */ public static final MapMode READ_WRITE = new MapMode("READ_WRITE"); // The string used to display the mapping mode. private final String displayName; /* * Private constructor prevents others creating new modes. */ private MapMode(String displayName) { this.displayName = displayName; } /** * Returns a string version of the mapping mode. * * @return this map mode as string. */ @Override public String toString() { return displayName; } } /** * Protected default constructor. */ protected FileChannel() { } /** * Requests that all updates to this channel are committed to the storage * device. * <p> * When this method returns, all modifications made to the platform file * underlying this channel have been committed if the file resides on a * local storage device. If the file is not hosted locally, for example on a * networked file system, then applications cannot be certain that the * modifications have been committed. * <p> * There are no assurances given that changes made to the file using methods * defined elsewhere will be committed. For example, changes made via a * mapped byte buffer may not be committed. * <p> * The <code>metadata</code> parameter indicates whether the update should * include the file's metadata such as last modification time, last access * time, etc. Note that passing <code>true</code> may invoke an underlying * write to the operating system (if the platform is maintaining metadata * such as last access time), even if the channel is opened read-only. * * @param metadata * {@code true} if the file metadata should be flushed in * addition to the file content, {@code false} otherwise. * @throws ClosedChannelException * if this channel is already closed. * @throws IOException * if another I/O error occurs. */ public abstract void force(boolean metadata) throws IOException; /** * Obtains an exclusive lock on this file. * <p> * This is a convenience method for acquiring a maximum length lock on a * file. It is equivalent to: * {@code fileChannel.lock(0L, Long.MAX_VALUE, false);} * * @return the lock object representing the locked file area. * @throws ClosedChannelException * the file channel is closed. * @throws NonWritableChannelException * this channel was not opened for writing. * @throws OverlappingFileLockException * either a lock is already held that overlaps this lock * request, or another thread is waiting to acquire a lock that * will overlap with this request. * @throws FileLockInterruptionException * the calling thread was interrupted while waiting to acquire * the lock. * @throws AsynchronousCloseException * the channel was closed while the calling thread was waiting * to acquire the lock. * @throws IOException * if another I/O error occurs while obtaining the requested * lock. */ public final FileLock lock() throws IOException { return lock(0L, Long.MAX_VALUE, false); } /** * Obtains a lock on a specified region of the file. * <p> * This is the blocking version of lock acquisition, see also the * <code>tryLock()</code> methods. * <p> * Attempts to acquire an overlapping lock region will fail. The attempt * will fail if the overlapping lock has already been obtained, or if * another thread is currently waiting to acquire the overlapping lock. * <p> * If the request is not for an overlapping lock, the thread calling this * method will block until the lock is obtained (likely by no contention or * another process releasing a lock), or until this thread is interrupted or * the channel is closed. * <p> * If the lock is obtained successfully then the {@link FileLock} object * returned represents the lock for subsequent operations on the locked * region. * <p> * If the thread is interrupted while waiting for the lock, the thread is * set to the interrupted state and throws a * {@link FileLockInterruptionException}. If this channel is closed while * the thread is waiting to obtain the lock then the thread throws a * {@link AsynchronousCloseException}. * <p> * There is no requirement for the position and size to be within the * current start and length of the file. * <p> * Some platforms do not support shared locks, and if a request is made for * a shared lock on such a platform, this method will attempt to acquire an * exclusive lock instead. It is undefined whether the lock obtained is * advisory or mandatory. * * @param position * the starting position for the locked region. * @param size * the length of the locked region in bytes. * @param shared * a flag indicating whether an attempt should be made to acquire * a shared lock. * @return the file lock object. * @throws IllegalArgumentException * if {@code position} or {@code size} is negative. * @throws ClosedChannelException * if this channel is closed. * @throws OverlappingFileLockException * if the requested region overlaps an existing lock or pending * lock request. * @throws NonReadableChannelException * if the channel is not opened in read-mode but shared is true. * @throws NonWritableChannelException * if the channel is not opened in write mode but shared is * false. * @throws AsynchronousCloseException * if this channel is closed by another thread while this method * is executing. * @throws FileLockInterruptionException * if the thread is interrupted while in the state of waiting on * the desired file lock. * @throws IOException * if another I/O error occurs. */ public abstract FileLock lock(long position, long size, boolean shared) throws IOException; /** * Maps the file into memory. There can be three modes: read-only, * read/write and private. After mapping, changes made to memory or the file * channel do not affect the other storage place. * <p> * Note: mapping a file into memory is usually expensive. * * @param mode * one of the three mapping modes. * @param position * the starting position of the file. * @param size * the size of the region to map into memory. * @return the mapped byte buffer. * @throws NonReadableChannelException * if the FileChannel is not opened for reading but the given * mode is "READ_ONLY". * @throws NonWritableChannelException * if the FileChannel is not opened for writing but the given * mode is not "READ_ONLY". * @throws IllegalArgumentException * if the given parameters of position and size are not correct. * Both must be non negative. {@code size} also must not be * bigger than max integer. * @throws IOException * if any I/O error occurs. */ public abstract MappedByteBuffer map(FileChannel.MapMode mode, long position, long size) throws IOException; /** * Returns the current value of the file position pointer. * * @return the current position as a positive integer number of bytes from * the start of the file. * @throws ClosedChannelException * if this channel is closed. * @throws IOException * if another I/O error occurs. */ public abstract long position() throws IOException; /** * Sets the file position pointer to a new value. * <p> * The argument is the number of bytes counted from the start of the file. * The position cannot be set to a value that is negative. The new position * can be set beyond the current file size. If set beyond the current file * size, attempts to read will return end of file. Write operations will * succeed but they will fill the bytes between the current end of file and * the new position with the required number of (unspecified) byte values. * * @param offset * the new file position, in bytes. * @return the receiver. * @throws IllegalArgumentException * if the new position is negative. * @throws ClosedChannelException * if this channel is closed. * @throws IOException * if another I/O error occurs. */ public abstract FileChannel position(long offset) throws IOException; /** * Reads bytes from this file channel into the given buffer. * <p> * The maximum number of bytes that will be read is the remaining number of * bytes in the buffer when the method is invoked. The bytes will be copied * into the buffer starting at the buffer's current position. * <p> * The call may block if other threads are also attempting to read from this * channel. * <p> * Upon completion, the buffer's position is set to the end of the bytes * that have been read. The buffer's limit is not changed. * * @param buffer * the byte buffer to receive the bytes. * @return the number of bytes actually read. * @throws AsynchronousCloseException * if another thread closes the channel during the read. * @throws ClosedByInterruptException * if another thread interrupts the calling thread during the * read. * @throws ClosedChannelException * if this channel is closed. * @throws IOException * if another I/O error occurs, details are in the message. * @throws NonReadableChannelException * if the channel has not been opened in a mode that permits * reading. */ public abstract int read(ByteBuffer buffer) throws IOException; /** * Reads bytes from this file channel into the given buffer starting from * the specified file position. * <p> * The bytes are read starting at the given file position (up to the * remaining number of bytes in the buffer). The number of bytes actually * read is returned. * <p> * If {@code position} is beyond the current end of file, then no bytes are * read. * <p> * Note that the file position is unmodified by this method. * * @param buffer * the buffer to receive the bytes. * @param position * the (non-negative) position at which to read the bytes. * @return the number of bytes actually read. * @throws AsynchronousCloseException * if this channel is closed by another thread while this method * is executing. * @throws ClosedByInterruptException * if another thread interrupts the calling thread while this * operation is in progress. The calling thread will have the * interrupt state set, and the channel will be closed. * @throws ClosedChannelException * if this channel is closed. * @throws IllegalArgumentException * if <code>position</code> is less than 0. * @throws IOException * if another I/O error occurs. * @throws NonReadableChannelException * if the channel has not been opened in a mode that permits * reading. */ public abstract int read(ByteBuffer buffer, long position) throws IOException; /** * Reads bytes from this file channel and stores them in the specified array * of buffers. This method attempts to read as many bytes as can be stored * in the buffer array from this channel and returns the number of bytes * actually read. It also increases the file position by the number of bytes * read. * <p> * If a read operation is in progress, subsequent threads will block until * the read is completed and will then contend for the ability to read. * <p> * Calling this method is equivalent to calling * {@code read(buffers, 0, buffers.length);} * * @param buffers * the array of byte buffers into which the bytes will be copied. * @return the number of bytes actually read. * @throws AsynchronousCloseException * if this channel is closed by another thread during this read * operation. * @throws ClosedByInterruptException * if the thread is interrupted by another thread during this * read operation. * @throws ClosedChannelException * if this channel is closed. * @throws IOException * if another I/O error occurs; details are in the message. * @throws NonReadableChannelException * if the channel has not been opened in a mode that permits * reading. */ public final long read(ByteBuffer[] buffers) throws IOException { return read(buffers, 0, buffers.length); } /** * Reads bytes from this file channel into a subset of the given buffers. * This method attempts to read all {@code remaining()} bytes from {@code * length} byte buffers, in order, starting at {@code targets[offset]}. It * increases the file position by the number of bytes actually read. The * number of bytes actually read is returned. * <p> * If a read operation is in progress, subsequent threads will block until * the read is completed and will then contend for the ability to read. * * @param buffers * the array of byte buffers into which the bytes will be copied. * @param start * the index of the first buffer to store bytes in. * @param number * the maximum number of buffers to store bytes in. * @return the number of bytes actually read. * @throws AsynchronousCloseException * if this channel is closed by another thread during this read * operation. * @throws ClosedByInterruptException * if the thread is interrupted by another thread during this * read operation. * @throws ClosedChannelException * if this channel is closed. * @throws IndexOutOfBoundsException * if {@code start < 0} or {@code number < 0}, or if * {@code start + number} is greater than the size of * {@code buffers}. * @throws IOException * if another I/O error occurs; details are in the message. * @throws NonReadableChannelException * if the channel has not been opened in a mode that permits * reading. */ public abstract long read(ByteBuffer[] buffers, int start, int number) throws IOException; /** * Returns the size of the file underlying this channel in bytes. * * @return the size of the file in bytes. * @throws ClosedChannelException * if this channel is closed. * @throws IOException * if an I/O error occurs while getting the size of the file. */ public abstract long size() throws IOException; /** * Reads up to {@code count} bytes from {@code src} and stores them in this * channel's file starting at {@code position}. No bytes are transferred if * {@code position} is larger than the size of this channel's file. Less * than {@code count} bytes are transferred if there are less bytes * remaining in the source channel or if the source channel is non-blocking * and has less than {@code count} bytes immediately available in its output * buffer. * <p> * Note that this channel's position is not modified. * * @param src * the source channel to read bytes from. * @param position * the non-negative start position. * @param count * the non-negative number of bytes to transfer. * @return the number of bytes that are transferred. * @throws IllegalArgumentException * if the parameters are invalid. * @throws NonReadableChannelException * if the source channel is not readable. * @throws NonWritableChannelException * if this channel is not writable. * @throws ClosedChannelException * if either channel has already been closed. * @throws AsynchronousCloseException * if either channel is closed by other threads during this * operation. * @throws ClosedByInterruptException * if the thread is interrupted during this operation. * @throws IOException * if any I/O error occurs. */ public abstract long transferFrom(ReadableByteChannel src, long position, long count) throws IOException; /** * Reads up to {@code count} bytes from this channel's file starting at * {@code position} and writes them to {@code target}. No bytes are * transferred if {@code position} is larger than the size of this channel's * file. Less than {@code count} bytes are transferred if there less bytes * available from this channel's file or if the target channel is * non-blocking and has less than {@code count} bytes free in its input * buffer. * <p> * Note that this channel's position is not modified. * * @param position * the non-negative position to begin. * @param count * the non-negative number of bytes to transfer. * @param target * the target channel to write to. * @return the number of bytes that were transferred. * @throws IllegalArgumentException * if the parameters are invalid. * @throws NonReadableChannelException * if this channel is not readable. * @throws NonWritableChannelException * if the target channel is not writable. * @throws ClosedChannelException * if either channel has already been closed. * @throws AsynchronousCloseException * if either channel is closed by other threads during this * operation. * @throws ClosedByInterruptException * if the thread is interrupted during this operation. * @throws IOException * if any I/O error occurs. */ public abstract long transferTo(long position, long count, WritableByteChannel target) throws IOException; /** * Truncates the file underlying this channel to a given size. Any bytes * beyond the given size are removed from the file. If there are no bytes * beyond the given size then the file contents are unmodified. * <p> * If the file position is currently greater than the given size, then it is * set to the new size. * * @param size * the maximum size of the underlying file. * @throws IllegalArgumentException * if the requested size is negative. * @throws ClosedChannelException * if this channel is closed. * @throws NonWritableChannelException * if the channel cannot be written to. * @throws IOException * if another I/O error occurs. * @return this channel. */ public abstract FileChannel truncate(long size) throws IOException; /** * Attempts to acquire an exclusive lock on this file without blocking. * <p> * This is a convenience method for attempting to acquire a maximum length * lock on the file. It is equivalent to: * {@code fileChannel.tryLock(0L, Long.MAX_VALUE, false);} * <p> * The method returns {@code null} if the acquisition would result in an * overlapped lock with another OS process. * * @return the file lock object, or {@code null} if the lock would overlap * with an existing exclusive lock in another OS process. * @throws ClosedChannelException * if the file channel is closed. * @throws OverlappingFileLockException * if a lock already exists that overlaps this lock request or * another thread is waiting to acquire a lock that will overlap * with this request. * @throws IOException * if any I/O error occurs. */ public final FileLock tryLock() throws IOException { return tryLock(0L, Long.MAX_VALUE, false); } /** * Attempts to acquire an exclusive lock on this file without blocking. The * method returns {@code null} if the acquisition would result in an * overlapped lock with another OS process. * <p> * It is possible to acquire a lock for any region even if it's completely * outside of the file's size. The size of the lock is fixed. If the file * grows outside of the lock that region of the file won't be locked by this * lock. * * @param position * the starting position. * @param size * the size of file to lock. * @param shared * true if the lock is shared. * @return the file lock object, or {@code null} if the lock would overlap * with an existing exclusive lock in another OS process. * @throws IllegalArgumentException * if any parameters are invalid. * @throws ClosedChannelException * if the file channel is closed. * @throws OverlappingFileLockException * if a lock is already held that overlaps this lock request or * another thread is waiting to acquire a lock that will overlap * with this request. * @throws IOException * if any I/O error occurs. */ public abstract FileLock tryLock(long position, long size, boolean shared) throws IOException; /** * Writes bytes from the given byte buffer to this file channel. * <p> * The bytes are written starting at the current file position, and after * some number of bytes are written (up to the remaining number of bytes in * the buffer) the file position is increased by the number of bytes * actually written. * * @param src * the byte buffer containing the bytes to be written. * @return the number of bytes actually written. * @throws NonWritableChannelException * if the channel was not opened for writing. * @throws ClosedChannelException * if the channel was already closed. * @throws AsynchronousCloseException * if another thread closes the channel during the write. * @throws ClosedByInterruptException * if another thread interrupts the calling thread while this * operation is in progress. The interrupt state of the calling * thread is set and the channel is closed. * @throws IOException * if another I/O error occurs, details are in the message. * @see java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer) */ public abstract int write(ByteBuffer src) throws IOException; /** * Writes bytes from the given buffer to this file channel starting at the * given file position. * <p> * The bytes are written starting at the given file position (up to the * remaining number of bytes in the buffer). The number of bytes actually * written is returned. * <p> * If the position is beyond the current end of file, then the file is first * extended up to the given position by the required number of unspecified * byte values. * <p> * Note that the file position is not modified by this method. * * @param buffer * the buffer containing the bytes to be written. * @param position * the (non-negative) position at which to write the bytes. * @return the number of bytes actually written. * @throws IllegalArgumentException * if <code>position</code> is less than 0. * @throws ClosedChannelException * if this channel is closed. * @throws NonWritableChannelException * if the channel was not opened in write-mode. * @throws AsynchronousCloseException * if this channel is closed by another thread while this method * is executing. * @throws ClosedByInterruptException * if another thread interrupts the calling thread while this * operation is in progress. The interrupt state of the calling * thread is set and the channel is closed. * @throws IOException * if another I/O error occurs. */ public abstract int write(ByteBuffer buffer, long position) throws IOException; /** * Writes bytes from all the given byte buffers to this file channel. * <p> * The bytes are written starting at the current file position, and after * the bytes are written (up to the remaining number of bytes in all the * buffers), the file position is increased by the number of bytes actually * written. * <p> * Calling this method is equivalent to calling * {@code write(buffers, 0, buffers.length);} * * @param buffers * the buffers containing bytes to write. * @return the number of bytes actually written. * @throws AsynchronousCloseException * if this channel is closed by another thread during this write * operation. * @throws ClosedByInterruptException * if another thread interrupts the calling thread while this * operation is in progress. The interrupt state of the calling * thread is set and the channel is closed. * @throws ClosedChannelException * if this channel is closed. * @throws IOException * if another I/O error occurs; details are in the message. * @throws NonWritableChannelException * if this channel was not opened for writing. */ public final long write(ByteBuffer[] buffers) throws IOException { return write(buffers, 0, buffers.length); } /** * Attempts to write a subset of the given bytes from the buffers to this * file channel. This method attempts to write all {@code remaining()} * bytes from {@code length} byte buffers, in order, starting at {@code * sources[offset]}. The number of bytes actually written is returned. * <p> * If a write operation is in progress, subsequent threads will block until * the write is completed and then contend for the ability to write. * * @param buffers * the array of byte buffers that is the source for bytes written * to this channel. * @param offset * the index of the first buffer in {@code buffers }to get bytes * from. * @param length * the number of buffers to get bytes from. * @return the number of bytes actually written to this channel. * @throws AsynchronousCloseException * if this channel is closed by another thread during this write * operation. * @throws ClosedByInterruptException * if another thread interrupts the calling thread while this * operation is in progress. The interrupt state of the calling * thread is set and the channel is closed. * @throws ClosedChannelException * if this channel is closed. * @throws IndexOutOfBoundsException * if {@code offset < 0} or {@code length < 0}, or if * {@code offset + length} is greater than the size of * {@code buffers}. * @throws IOException * if another I/O error occurs; details are in the message. * @throws NonWritableChannelException * if this channel was not opened for writing. */ public abstract long write(ByteBuffer[] buffers, int offset, int length) throws IOException; }