Java 文件通道

1 FileChannel API

    FileChannel类可以实现常用的readwrite以及scatter/gather操作,同时提供了很多专用于文件的新方法。

    文件通道总是阻塞的,因此不能被置于非阻塞模式。对于文件IO,最强大之处在于异步IO,它允许一个进程可以从操作系统请求一个或多个IO操作而不必等待这些操作的完成。

    FileChannel对象不能直接创建。一个FileChannel实例只能通过在一个开打的file对象(RandomAccessFileFileInputStreamFileOutputStream)上调用getChannel()方法获取。FileChannel对象具有与file对象相同的访问权限。

package java.nio.channels; 
public abstract class FileChannel  extends AbstractChannel  
implements ByteChannel, GatheringByteChannel, ScatteringByteChannel 
{ 
    // This is a partial API listing 
    // All methods listed here can throw java.io.IOException 

    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 lo ng transferTo (long position, long count, WritableByteChannel target) 
    public abstract long transferFrom (ReadableByteChannel src, 
    long position, long count) 
}

 

    FileChannel对象是线程安全的。多个进程可以同一个实例上并发调用方法而不会引起任何问题,但并非所有的操作都是多线程的。影响通道位置或者影响文件大小的操作都是单线程的。如果一个线程已经在执行会影响通道位置或文件大小的操作,其他尝试进行此类操作之一的线程必须等待。

2 访问文件

  每个FileChannel对象都同一个文件描述符(file descriptor)有一对一的关系。

 

  

    同底层的文件描述符一样,每个FileChannel都有一个叫'file position'的概念,该position值决定文件中哪一处的数据接下来被读或写。MappedByteBuffer类使得我们可以通过ByteBuffer API来访问数据文件。   

    第二种形式position()方法带Long参数将通道的position设置为指定值。不可以把position设置到超出文件尾,这样会把position设置为指定值而不改变文件大小(当磁盘上一个文件的分配空间小于它的文件大小时会出现“文件空洞”)   

    FileChannel 位置(position)是从底层的文件描述符获得的,该position同时被作为通道引用获。   

    类似于缓冲区的get( )  put( )方法,当字节被read( ) write( ) 方法传输时,文件position会自动更新。如果position值达到了文件大小的值(文件大小的值可以通过size( )方法返回),read( ) 方法会返回一个文件尾条件值(-1)。可是,不同于缓冲区的是,如果实现write( ) 方法时position前进到超过文件大小的值,该文件会扩展以容纳新写入的字节。

    同样类似于缓冲区,也有带position参数的绝对形式的read( ) 和  write( ) 方法。这种绝对形式的方法在返回值时不会改变当前的文件position。

    当需要减少一个文件的size 时,truncate( )方法会砍掉您所指定的新size 值之外的所有数据。

    force( ) ,该方法告诉通道强制将全部待定的修改都应用到磁盘的文件上。

    force( ) 方法的布尔型参数表示在方法返回值前文件的元数据(metadata)是否也要被同步更新到磁盘。元数据指文件所有者、访问权限、最后一次修改时间等信息。 

3  文件锁定

    锁(lock)可以使共享的或独占的。并非所有的操作系统和文件都支持共享文件锁。

    FileChannel实现的文件锁定模型的一个重要注意项:锁的对象是文件而不是通道或者线程。

    如果一个线程在某文件上获得一个独占锁,然后第二个线程利用一个单独打开的通道来请求该文件,那么第二个线程的请求会被批准,但如果这两个线程运行在不同的JVM上,第二个线程会阻塞,因为锁最终是由操作系统或文件系统来判优的,并且几乎总是在进程级而非线程级上判优。如果需要控制多个线程的并发访问,内存映射文件可能是一个合适的选择。  

  public abstract class FileChannel  extends AbstractChannel  
  implements ByteChannel, GatheringByteChannel, ScatteringByteChannel 
  { 
      // This is a partial API listing  
      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) 
   } 

    锁是在文件内部区域上获得的,调用带参数的Lock( )方法会指定文件内部锁定区域的开始position 以及锁定区域的size。第三个参数shared表示获取的锁是共享的还是独占的。                                         

  要获得一个共享锁,您必须先以只读权限打开文件,而请求独占锁时则需要写权限。

    锁定区域的范围不一定要限制在文件的size值以内,锁可以扩展从而超出文件尾。因此,我们可以提前把待写入数据的区域锁定,我们也可以锁定一个不包含任何文件内容的区域。不带参数的简单形式的lock()方法是一种在整个文件上请求独占锁的便捷方法,锁定区域等于它能到达的最大范围。

    fileChannel.lock (0L, Long.MAX_VALUE, false);

    tryLocklock方法相同,但如果请求的锁不能立即获取到则返回一个Null

  public abstract class FileLock
  { 
      public final FileChannel channel( ) 
      public final long position( ) 
      public final long size( ) 
      public final boolean isShared( ) 
      public final boolean overlaps (long position, long size) 
      public abstract boolean isValid( ); 
      public abstract void release( ) throws IOException; 
   }

   FileLock类封装一个锁定的文件区域。Fi leLock 对象由FileChannel 创建并且总是关联到那个特定的通道实例。

   一个FileLock对象创建之后即有效,直到它的release( ) 方法被调用或它所关联的通道被关闭或Java 虚拟机关闭时才会失效。锁的有效性可能会随着时间而改变,不过它的其他属性位置(position)、范围大小(size )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值