/** * 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 long transferTo(long position, long count, WritableByteChannel target) throws IOException { checkOpen(); if (!target.isOpen()) { throw new ClosedChannelException(); } checkReadable(); if (target instanceof IOCipherFileChannel) { ((IOCipherFileChannel) target).checkWritable(); } if (position < 0 || count < 0) { throw new IllegalArgumentException("position=" + position + " count=" + count); } if (count == 0 || position >= size()) { return 0; } count = Math.min(count, size() - position); try { ByteBuffer buffer = ByteBuffer.allocate((int) count); read(buffer, position); buffer.flip(); return target.write(buffer); } finally { // TODO determine whether we have memory leaking or perf issues here #567 } }
@Override public void close() throws IOException { synchronized (this) { if (channel != null) { channel.close(); } if (shouldClose) { IoUtils.close(fd); } else { // An owned fd has been invalidated by IoUtils.close, but // we need to explicitly stop using an unowned fd (http://b/4361076). fd = new FileDescriptor(); } } }