FileChannel
FileChannel 总是阻塞的,因此不能被设置成非阻塞模式。
FileChannel 对象不能直接创建。一个 FileChannel 实例只能通过在一个打开的 file 对象(RandomAccessFile、FileInputStream或 FileOutputStream)上调用 getChannel() 方法 获取。
public abstract class FileChannel extends AbstractInterruptibleChannel implements ByteChannel, GatheringByteChannel, ScatteringByteChannel { public abstract int read(ByteBuffer dst, long position); public abstract int write(ByteBuffer src, long position); public abstract long size(); public abstract long position(); public abstract void position(long newPosition); public abstract void truncate(long size); public abstract void force(boolean metaData); public final FileLock lock(); public abstract FileLock lock(long position, long size, boolean shared); public final FileLock tryLock(); public abstract FileLock tryLock(long position, long size, boolean shared); public abstract MappedByteBuffer map(MapMode mode, long position, long size); public static class MapMode { public static final MapMode READ_ONLY; public static final MapMode READ_WRITE; public static final MapMode PRIVATE; } public abstract long transferTo(long position, long count, WritableByteChannel target); public abstract long transferFrom(ReadableByteChannel src, long position, long count); }
FileChannel 类本身是抽象的, getChannel() 方法获取的实际对象是一个具体子类的一个实例 ,该子类可能使用本地代码来实现以上 API 方法中的一些或全部。
FileChannel 对象是线程安全的。多个进程可以在同一个实例上并发调用方法而不会引起任何问题,不过并非所有的操作都是多线程的。影响通道位置或者影响文件大小的操作都是单线程的。如果有一个线程已经在执行会影响通道位置或文件大小的操作,那么其他试进行此类操作之一的线程必须等待。
FileChannel 是一个反映 Java 虚拟机外部一个具体对象的抽象。
FileChannel 类保证同一个 Java 虚拟机上的所有实例看到的某个文件的视图均是一致的。
每个 FileChannel 对象都同一个文件描述符(file descriptor)有一对一的关系。
FileChannel、RandomAccessFile 和 POSIX I/O system calls 三者在 方法上的对应关系。
FileChannel | RandomAccessFile | POSIX system call |
---|---|---|
read( ) | read( ) | read( ) |
write( ) | write( ) | write( ) |
size( ) | length( ) | fstat( ) |
position( ) | getFilePointer( ) | lseek( ) |
position (long newPosition) | seek( ) | lseek( ) |
truncate( ) | setLength( ) | ftruncate( ) |
force( ) | getFD().sync( ) | fsync( ) |
每个 FileChannel 都有一个 position 值来决定文件中哪一处的数据接下来被读或者写。
如果试将通道 position 设置为一个负值会导致 java.lang.IllegalArgumentException 异常。
把 position 设置到超出文件 ,这样做会把 position 设置为指定值而不改变文件大小。
FileChannel 位置(position)是从底层的文件 述符获得的,该 position 同时被作为通道引用 获取来源的文件对象共享。这也就意味着一个对象对该 position 的更新可以被另一个对象看到:
RandomAccessFile randomAccessFile = new RandomAccessFile ("filename", "r"); randomAccessFile.seek (1000); FileChannel fileChannel = randomAccessFile.getChannel( ); // This will print "1000" System.out.println ("file pos: " + fileChannel.position( )); randomAccessFile.seek (500); // This will print "500" System.out.println ("file pos: " + fileChannel.position( )); fileChannel.position (200); // This will print "200" System.out.println ("file pos: " + randomAccessFile.getFilePointer( ));
当需要减少一个文件的 size 时,truncate( )方法会 您所指定的新 size 值之外的所有数据。
如果当前 size 大于新 size,超出新 size 的所有字节都会被丢弃。
如果提供的新 size 值大于或等于当前的文件 size 值,该文件不会被修改。
调用 truncate() 方法后 position 会被设置成提供的新 size。
force() 方法告诉通道强制将全部待定的修改都应用到磁盘的文件上。所有的现代文件系统都会缓存数据和延迟磁盘文件更新以提高性能。调用 force( )方法要求文件的所有待定修改立即同步到磁盘。
【参考资料】
- Java Nio
—EOF—