新I/O

Java NIO 新特性概览
本文介绍Java SE 1.4中引入的新I/O特性,包括非阻塞I/O、内存映射文件及文件加锁机制。重点讲解了如何通过FileChannel进行内存映射,以及如何使用不同模式进行文件读写,还介绍了文件锁的概念及其在不同操作系统上的表现。

Java SE 1.4引入了大量用于改进输入/输出处理机制的特性,它们位于java.nio包中,合称“新I/O”。 

这个包中包含对下列特性的支持:字符集编码器和解码器,非阻塞的I/O ,内存映射文件,文件加锁机制 。字符集编码器和解码器在前面已经说过了。

内存映射文件
大多数操作系统都可以利用虚拟内存实现来将一个文件或者文件的一部分“映射”到内存中。然后,这个文件就可以当作是内存数组一样地访问,这比传统的文件操作要快得多 。内存映射比使用带缓冲的顺序输入要稍微快一点,但是比使用RandomAccessFile快很多。
当然,精确的值因机器不同会产生很大的差异,但是很明显,如果需要使用随机访问,那么性能受损是不可避免的。另一方面,对于中等尺寸文件的顺序读入没有必要使用内存映射。

首先,从文件中获得一个通道( channel),通道是用于磁盘文件的一种抽象,它使我们可以访问诸如内存映射、文件加锁机制以及文件间快速数据传递等操作系统特性。我们可以通过调用getChannel方法来获得通道,这个方法已经添加到了FileInputStreamFileOutputStreamRandomAccessFile类中。

FileInputStream f = new FileInputStream(xxx);
FileChannel chnanel = f.getChannel();
然后,通过调用FileChannel类的map方法从这个通道中获得一个MappedByteBuffer。你可以指定想要映射的文件区域与映射模

式,有三种模式可以得到支持:

FileChannel.MapMode.READ_ONLY:所产生的缓冲区是只读的,任何对该缓冲区写入的尝试都会导致ReadOnlyBufferException异常。
FileChannel.MapMode.READ_WRITE:所产生的缓冲区是可写的,任何修改都会在某个时刻写回到文件中。注意,其他映射同一个
件的程序可能不能立即看到这些修改,多个程序同时进行文件映射的确切行为是依赖于操作系统的。

FileChannel.MapMode.PRIVATE:所产生的缓冲区是可写的,但是任何修改对这个缓冲区来说都是私有的,不会传播到文件中。有了缓冲区,就可以使用ByteBuffer类和Buffer超类的方法读写数据了。

文件加锁机制

文件锁可以控制对文件或文件中某个范围的字节的访问,但是,文件加锁机制在不同的操作系统之间变化很大。

FileChannel
FileLock lock()
在整个文件上获得一个独占的锁,这个方法将阻塞直至获得锁。
FileLock tryLock()
在整个文件上获得一个独占的锁,或者在无法获得锁的情况下返回null。
FileLock lock(long position, long size, boolean shared)
FileLock tryLock(long position, long size, boolean shared)
在文件的一个区域上获得锁。第一个方法将阻塞直至获得锁,而第二个方法将在无法获得锁时返回null。
参数: position 要锁定区域的起始位置
size 要锁定区域的尺寸
shared true为共享锁, false为独占锁
FileLock
void release()
释放这个锁。
MappedByteBuffer map(FileChannel.MapMode mode, long position, long size)将文件的一个区域映射到内存中。
参数: mode FileChannel.MapMode类中的常量READ_ONLY、 READ_WRITE、或PRIVATE之一
position 映射区域的起始位置
size 映射区域的大小
buffer
boolean hasRemaining()
如果当前的缓冲区位置没有达到这个缓冲区的界限位置则返回true。
int limit()
返回这个缓冲区的界限位置,即没有任何值可用的第一个位置。
ByteBuffer
byte get()从当前位置获得一个字节,并将当前位置推到下一个字节。
byte get(int index)从指定索引处获得一个字节。
ByteBuffer put(byte b)向当前位置推入一个字节,并将当前位置推到下一个字节。返回对这个缓冲区的引用。
ByteBuffer put(int index, byte b)向指定索引处推入一个字节。返回对这个缓冲区的引用。
ByteBuffer get(byte[] destination)
ByteBuffer get(byte[] destination, int offset, int length)
用缓冲区中的字节来填充字节数组,或者字节数组的某个区域,并将当前位置向前推读入的字节数个位置。如果缓冲区不够,那么就不会读入任何字节,并抛出BufferUnderflowException。返回对这个缓冲区的引用。
参数: destination 要填充的字节数组
offset 要填充区域的偏移量length 要填充区域的长度
ByteBuffer put(byte[] source)
ByteBuffer put(byte[] source, int offset, int length)
将字节数组中的所有字节或者给定区域的字节都推入缓冲区中,并将当前位置向前推写出的字节数个位置。如果缓冲区不够,那么就不会读入任何字节,并抛出BufferUnderflow Exception。返回对这个缓冲区的引用。
参数: source 要写出的数组
offset 要写出区域的偏移量
length 要写出区域的长度
Xxx getXxx()
Xxx getXxx(int index)
ByteBuffer putXxx(xxx value)
ByteBuffer putXxx(int index, xxx value)
获得或放置一个二进制数。 Xxx Int、 Long、 Short、 Char、 Float或Double中的一个。
ByteBuffer order(ByteOrder order)
ByteOrder order()
设置或获得字节顺序, order的值是ByteOrder类的常量BIG_ENDIAN或LITTLE_ENDIAN中
的一个
Buffer clear()通过将位置复位到0,并将界限复位到容量,使这个缓冲区为写出做好准备。返回this。
Buffer flip()通过将界限设置到位置,并将位置复位到0,使这个缓冲区为读入做好准备。返回this。
Buffer rewind()通过将读写位置复位到0,并保持极限不变,使这个缓冲区为重新读入相同的值做好准备。返回this。
Buffer mark()将这个缓冲区的标记设置到读写位置,返回this。
Buffer reset()将这个缓冲区的位置设置到标记,从而允许被标记的部分可以再次被读入或写出,返回this。
int remaining()返回剩余可读入或可写出的值的数量,即界限与位置之间的差异。
int position()返回这个缓冲区的位置。
int capacity()返回这个缓冲区的容量。


charbuffer
char get()
CharBuffer get(char[] destination)
CharBuffer get(char[] destination, int offset, int length)
从这个缓冲区的位置处开始,获得一个char值,或者某个范围的char值,然后将位置向前推过所读入的字符。最后两个方法返回this。
CharBuffer put(char c)
CharBuffer put(char[] source)
CharBuffer put(char[] source, int offset, int length)
CharBuffer put(String source)
CharBuffer put(CharBuffer source)
从这个缓冲区的位置处开始,推入一个char值,或者某个范围的char值,然后将位置向前推过所写出的字符。
CharBuffer read(CharBuffer destination)
从这个缓冲区中获得char值,然后将它们推入目标缓冲区,直至达到目标缓冲区的界限。返回this。


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值