Java Nio Buffer 十

2018/01/12 Java

Java Nio Buffer 十

访问文件

每个 FileChannel 对象都同一个文件描述符(file descriptor)有一对一的关系,所以 FileChannel 对象新添加的方法同POSIX标准中常用的I/O 是紧密对应的。 下面给出一个表格列出 FileChannel , RandomAccessFile 和 POSIX I/O 系统调用三者在方法上的对应关系:

FileChannel RandomAccessFile POSIX system call
read() read() read()
write() write() write()
size() length() fstat()
position() getFilePointer() lseek()
postition(long newPosition) getFilePointer() lseek()
truncate() setLength() ftruncate()
force() getFD().sync() fsync()

下面是FileChannel 的类签名:

public abstract class FileChannel
    extends AbstractChannel
    implements ByteChannel, GatheringByteChannel, ScatteringByteChannel
{
    // This is a partial API listing
    public abstract long position( )
    public abstract void position (long newPosition)
    public abstract int read (ByteBuffer dst)
    public abstract int read (ByteBuffer dst, long position)
    public abstract int write (ByteBuffer src)
    public abstract int write (ByteBuffer src, long position)
    public abstract long size( )
    public abstract void truncate (long size)
    public abstract void force (boolean metaData)
}

每个FileChannel对象都有一个”file position”的概念,这个值会决定文件哪一处的数据将被读写。FileChannel和缓冲区很类似,并且MappedByteBuffer类使得可以使用ByteBuffer API 来访问文件数据。 两种形式的Position()方法,不带参数的函数可以获得当前文件的position值,返回值是Long型,并表示文件中的当前直接位置。带有Long参数的函数会将通道的position值设置为指定值。如果position为负数,会产生异常。如果position大于文件的最大长度,然后再写入的话,会产生文件黑洞。对于内容系数的文件,大多数现代文件系统只为实际卸乳的数据分配磁盘空间,读取数据的时候所有的空洞都只会用”0“填充。
position值是从底层文件描述符中获取到的,所以该值会被通道饮用获取来源的文件对象共享。一个对象对该值的更新另一个对象可以看到。
数据使用read()write传输时,文件的position会自动更新,如果到了文件尾,read()会返回-1,write()会自动更新改值。使用带参数的read()write时候不需要更新position值,回事的操作更有效率。同时,多个线程可以并发访问同一个文件不会相互产生干扰,因为每次的调用都是原子性的,操作不需要依靠调用自建系统所维护的文件状态。

truncate()会产生副作用,会丢弃掉size意外的所有字节,如果设定size大于文件先有的大小,文件不会被修改。position都会被改成truncate()函数设定的值。

force()函数会让通道强制将全部待定的修改都应用到磁盘的文件上。但是JVM依赖操作系统的实现,如果需要再程序崩溃的时候保证文件的完整性,需要以来操作系统的实现。

Show Disqus Comments

Search

    Table of Contents