文件通道,是一种特殊的通道。
对于文件通道来说,是不能阻塞的。所以并不能设置非阻塞模式。
对于异步文件I/O来说,这是很多操作系统支持的,NIO也会增强。
一个FileChannel只能从RandomAccessFile,FileInputStream和FileOutputStream来获取(getChannel),然后你就获得了某种能力,请看:
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 long transferTo (long position, long count, WritableByteChannel target) public abstract long transferFrom (ReadableByteChannel src, long position, long count)
}
以上的操作,都会抛出java.io.IOException
FileChannel对象是线程安全的,但是注意的是,影响到通道位置和文件大小的操作是单线程的。
对于同一个虚拟机,我们看到的对于某一个文件的FileChannel实例视图都是一致的。
FileChannel对于的操作和POSIX中的一些API函数很相像。
FileChannelRandomAccessFile | POSIX system callread() | read() | read()\nwrite() | write() | write()\nsize() | length() | fstat()\nposition() | getFilePointer() | lseek()\nposition(long newPosition) | seek() | lseek()\ntruncate() | setLength() | ftruncate()\nforce() | getFD().sync() | fsync()\n |
FileChannel里有一个position属性,表示下一个要读取的文件位置。这个和缓冲区有点像。但是可以超过这个值。如果write的position超过了文件大写,就会增大文件,有可能造成空洞文件。如果是read的话,到达文件尾,则是返回-1.
如果带有一个long参数的position则可以设置文件的位置大小,这是并不改变文件大小。只有当read或者write的时候,才真正的改变。
注意position是从底层描述符中得来的,被作为通道引用获去来源的文件共享对象,所以改变她,其他的对象可以看到。
trucate函数会把新的size以外的数据清除。如果size大于原来的size,那么position会被改变成新的size。
对于force函数,则是一个同步磁盘函数。把修改都应用到磁盘上。如果带有boolean型参数,那么表明是否要把元数据也同步。元数据是指,文件的所有者,访问权限,上次修改时间等信息。这要看具体的应用,因为同步这些信息会有额外的底层I/O操作。
文件锁。
文件锁针对的是文件,所以和通道无关。一般来说分为共享锁(shared)和独占锁(exclusive)。
注意,如果一个进程下的另一个线程访问一个加独占锁的文件,是可以的。因为这是底层操作系统的实现。只是针对不同的进程。
所以,也有可能在某些操作系统上,独占锁只是一个建议锁,非强制性的。
关于管道上的锁,有如下操作。
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可以锁住一个文件的某个区域。而且这个区域可以使比文件还大。
超出文件尾的。这样,新写入的内容也被锁住。使用lock可能会阻塞,等待前一个lock被释放。
tryLock和lock一样。只是如果当时没有可用锁,就立即返回一个null,而不是阻塞。
FileLock 类如下:
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对象创建就生效。注意,创建以后,position,是否独占,大小就不能改变了。
FileLock是线程安全的,可以多个线程同时访问一个锁。注意,在你不确定操作系统是否支持独占性时,使用isShared()来判断是否该锁支持共享。
如果你要查看一个感兴趣的区域是否与当前的锁有冲突,可以使用 overlaps,这个函数返回的是当前进程上的,即使是返回为false,也不一定可以获取到FileLock。
最后,使用文件锁,一定要释放。使用try...catch...finally
FileLock lock = fileChannel.lock( )
try {
<perform read/write/whatever on channel>
} catch (IOException)
[ <handle unexpected exception> }
finally {
lock.release( )
}
注意,FileLock是针对不同进程的。如果在一个进程内,锁是无意义的。
分享到:
相关推荐
[第7节] Java NIO流-文件通道操作.flv [第8节] Java NIO流-选择器 .flv [第9节] Java NIO流-选择器操作.flv 四、Mina视频教程 00、Mina视频课程介绍.flv 01、Mina服务端helloWorld入门.flv 02、Mina客户端...
相同的回显服务器,但使用NIO2异步通道。 创建10000个客户端连接的类,您可以在nio服务器上测试负载。 监视服务API的简单用法。 监视预定义目录中的更改的类。 您可以播放生成的jar文件。 请按照以下步骤操作: ...
Java NIO 源码适合初学者,里面包括通道和Buffer的基本适用,以及文件锁,和内存文件映射等等
Java NIO通道:通道基础、文件通道、Socket通道、工具类 Java NIO缓冲区:基础、缓冲区(Buffer)、创建缓冲区、直接缓冲区(DirectByteBuffer) Java NIO选择器:核心概念、选择器使用、Demo、选择器深入、
主要介绍了Java NIO异步文件通道原理及用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
NIO将以更加高效的方式进行文件的读写操作。 Java NIO与普通IO的主要区别 io nio 面向流 面向缓冲区(buffer,channel) 堵塞io 非堵塞io - 选择器 java nio主要的核心组件 缓冲区 buffer 通道 Channels 选择器 ...
教程内容涵盖:阻塞和非阻塞IO、Channel通道、Buffer缓冲区、Selector选择器、Pipe管道、FileLock文件锁,以及Path、Files、异步FileChannel和Charset字符编码等,并通过一个多人聊天室的综合案例,把所有的NIO知识...
Java IO 体系 - Java IO 体系 ...Java IO 是一个庞大的知识体系,很多人学着学着就会学懵了,包括我在内也是如此,所以本文将会从 Java 的 BIO 开始,一步一步深入学习,引出 JDK1.4 之后出现的 NIO
Java NIO非堵塞应用通常适用用在I/O读写等方面,我们知道,系统运行的性能瓶颈通常在I/O读写,包括对端口和文件的操作上,过去,在打开一个I/O通道后,read()将一直等待在端口一边读取字节内容,如果没有内容进来,...
在以往的java的IO操作的过程中都是面向字节流操作,并且读写操作是单向的操作,而在java1.4添加nio包新的io不再像以前的标准的io操作一样面向流操作,而NIO是面向块的操作,并且有通道、缓冲区等重要的部分组成。...
NIO同样拥有文件读写,网络通信等IO操作,今天我们来看看NIO中的TCP网络通信的使用方法。 2. Java NIO 三大核心 Java NIO 有三大核心要素:Channel、Buffer和Selector。Java IO 的操作都是基于输入输出流的,而NIO则...
java.nio.channels 定义了各种通道,这些通道表示到能够执行 I/O 操作的实体(如文件和套接字)的连接;定义了用于多路复用的、非阻塞 I/O 操作的选择器。 java.nio.channels.spi 用于 java.nio.channels 包的服务...
所以,jdk1.4发布了NIO包,NIO的文件读写设计颠覆了传统IO的设计,采用『通道』+『缓存区』使得新式的IO操作直接面向缓存区,并且是非阻塞的,对于效率的提升真不是一点两点,我们一起来看看。我们说过,NIO的核心...
尚硅谷_NIO_通道的数据传输与内存映射文件 ·06. 尚硅谷_NIO_分散读取与聚集写入 ·07. 尚硅谷_NIO_字符集 Charset ·08. 尚硅谷_NIO_阻塞与非阻塞 ·09. 尚硅谷_NIO_阻塞式 ·10. 尚硅谷_NIO_非阻塞式 ·11. ...
NIO于原来的IO有相同的功能,但是他们之间的使用方式是完全不同的,NIO是面向缓冲区,面向通道的的IO操作,NIO拥有更加高效的进行文件读写。 另外NIO在网络编程可以是一个无阻塞的IO交互,可以大大提升Socket交互的...
NIO包(java.nio.*)引入了四个关键的抽象数据类型,它们共同解决传统的I/O类中的一些问题。 1. Buffer:它是包括数据且用于读写的线形表结构。当中还提供了一个特殊类用于内存映射文件的I/O操作。 2. ...
o Clojure对java.nio的支持。 将clojure.java.io的输入流,输出流和复制功能扩展到java.nio类。 定义新的强制功能缓冲区,字节缓冲区,字符缓冲区,双缓冲区,浮点缓冲区,整数缓冲区,长缓冲区,短缓冲区,通道,可...
2、使用java NIO读取被嵌入的文件,将其转换为byte数组,需要特别指出的是原生方法得到是byte类型的数组,但是算法实现需要更加精细的操作,所以还需要对得到的byte数组进行进一步的转换封装,将其转换成形如10101...
在软件系统中,由于IO的速度要比内存慢...使用java.nio.charset.Charset作为字符集编码解码解决方案;增加通道(channel)对象,作为新的原始I/O抽象;支持锁和内存映射文件的文件访问接口;提供了基于Selector的异步网