class FileNio extends FileBase {

    private final String fileName;
    private final RandomAccessFile file;
    private final FileChannel channel;

    FileNio(String fileName, String mode) throws IOException {
        this.fileName = fileName;
        file = new RandomAccessFile(fileName, mode);
        channel = file.getChannel();
    }

    @Override
    public void implCloseChannel() throws IOException {
        file.close(); // 内部会调用channel.close()
    }

    @Override
    public long position() throws IOException {
        return channel.position();
    }

    @Override
    public long size() throws IOException {
        return channel.size();
    }

    @Override
    public int read(ByteBuffer dst) throws IOException {
        return channel.read(dst);
    }

    @Override
    public FileChannel position(long pos) throws IOException {
        channel.position(pos);
        return this;
    }

    @Override
    public int read(ByteBuffer dst, long position) throws IOException {
        return channel.read(dst, position);
    }

    @Override
    public int write(ByteBuffer src, long position) throws IOException {
        return channel.write(src, position);
    }

    @Override
    public FileChannel truncate(long newLength) throws IOException {<FILL_FUNCTION_BODY>}

    @Override
    public void force(boolean metaData) throws IOException {
        channel.force(metaData);
    }

    @Override
    public int write(ByteBuffer src) throws IOException {
        try {
            return channel.write(src);
        } catch (NonWritableChannelException e) {
            throw new IOException("read only");
        }
    }

    @Override
    public synchronized FileLock tryLock(long position, long size, boolean shared) throws IOException {
        return channel.tryLock(position, size, shared);
    }

    @Override
    public String toString() {
        return "nio:" + fileName;
    }
}

        long size = channel.size();
        if (newLength < size) {
            long pos = channel.position();
            channel.truncate(newLength);
            long newPos = channel.position();
            if (pos < newLength) {
                // position should stay
                // in theory, this should not be needed
                if (newPos != pos) {
                    channel.position(pos);
                }
            } else if (newPos > newLength) {
                // looks like a bug in this FileChannel implementation, as
                // the documentation says the position needs to be changed
                channel.position(newLength);
            }
        }
        return this;
    
<methods>public non-sealed void <init>() ,public void force(boolean) throws java.io.IOException,public java.nio.channels.FileLock lock(long, long, boolean) throws java.io.IOException,public java.nio.MappedByteBuffer map(java.nio.channels.FileChannel.MapMode, long, long) throws java.io.IOException,public abstract long position() throws java.io.IOException,public abstract java.nio.channels.FileChannel position(long) throws java.io.IOException,public abstract int read(java.nio.ByteBuffer) throws java.io.IOException,public synchronized int read(java.nio.ByteBuffer, long) throws java.io.IOException,public long read(java.nio.ByteBuffer[], int, int) throws java.io.IOException,public abstract long size() throws java.io.IOException,public long transferFrom(java.nio.channels.ReadableByteChannel, long, long) throws java.io.IOException,public long transferTo(long, long, java.nio.channels.WritableByteChannel) throws java.io.IOException,public abstract java.nio.channels.FileChannel truncate(long) throws java.io.IOException,public java.nio.channels.FileLock tryLock(long, long, boolean) throws java.io.IOException,public abstract int write(java.nio.ByteBuffer) throws java.io.IOException,public synchronized int write(java.nio.ByteBuffer, long) throws java.io.IOException,public long write(java.nio.ByteBuffer[], int, int) throws java.io.IOException<variables>