简介: NIO支持面向缓冲区的、基于 通道的IO操作。NIO将以更加高效的方式进行文 件的读写操作。
需要获取 用于连接 IO 设备的通道以及用于容纳数据的缓冲区。然后操作缓冲区,对数据进行处理
Buffer
简介: 保存相同数据类型(基本数据类型)的容器
ByteBuffer 、CharBuffer 、ShortBuffer 、IntBuffer 、LongBuffer 、FloatBuffer、DoubleBuffer
static XxxBuffer **allocate**(int capacity) : 创建一个容量为capacity 的 XxxBuffer 对象
概念:
➢ 容量(capacity) :表示 Buffer 最大数据容量,缓冲区容量不能为负,并且创 建后不能更改。
➢ 限制(limit):第一个不应该读取或写入的数据的索引,即位于limit 后的数据 不可读写。缓冲区的限制不能为负,并且不能大于其容量。
➢ 位置(position):下一个要读取或写入的数据的索引。缓冲区的位置不能为 负,并且不能大于其限制
➢ 标记(mark)与重置(reset):标记是一个索引,通过Buffer 中的mark() 方法 指 定 Buffer 中一个特定的position,之后可以通过调用 reset() 方法恢复到这 个 position.
直接与非直接缓冲区
简介: 直接缓冲区的内容驻留在常规的垃圾回收堆之外,所以对应用程序的内存需求量较小。避免受系统的影响
- Buffer的
allocateDirect()工厂方法来创建。此方法返回的缓冲区进行分配和取消 分配所需成本通常高于非直接缓冲区。 - 通过FileChannel的
map()方法将文件区域直接映射到内存中来创建。该方法返回 MappedByteBuffer
Channel
简介:直接与IO流节点连接, 只不过Channel 本身不能直接访问数据,Channel 只能与 Buffer 进行交互
实现类
- FileChannel:用于读取、写入、映射和操作文件的通道。 常用方法如下:
- DatagramChannel:通过 UDP 读写网络中的数据通道。
- SocketChannel:通过 TCP 读写网络中的数据。
- ServerSocketChannel:可以监听新进来的 TCP 连接,对每一个新进来的连接都会创建一个 SocketChannel。
获取通道
一、**getChannel()**方法
以下支持FileInputStream、FileOutputStream、RandomAccessFile、DatagramSocket、Socket、 ServerSocket
二、Files 类的静态方法**newByteChannel()**获 取字节通道。
三、通过通道的静态方法**open()**打开并返回指定通道
方法:
- 将数据从源通道传输到其他 Channel 中
** transferFrom(fromChannel,count、position)**、 **transferTo(position、count、toChannel)**
步骤:
一、打开指定路径的文件通道,默认情况下,通道打开时用于读入FileChannel channel = FileChannel._open_(path, StandardOpenOption._APPEND_);
二、将文件的一个区域映射到缓冲区中MappedByteBuffer** buffer **= channel.map(FileChannel.MapMode._READ_ONLY_, 0, channel.size());
通过调用FileChannel类的map方法从这个通道中获得一个ByteBuffer缓冲区
FileChannel.MapMode.READ_ONLY:所产生的缓冲区是只读的,任何对该缓冲区写入的尝试都会导致ReadOnlyBufferException异常。FileChannel.MapMode.READ_WRITE:所产生的缓冲区是可写的,任何修改都会在某个时刻写回到文件中。注意,其他映射同一个文件的程序可能不能立即看到这些修改,多个程序同时进行文件映射的确切行为是依赖于操作系统的。FileChannel.MapMode.PRIVATE:所产生的缓冲区是可写的,但是任何修改对这个缓冲区来说都是私有的,不会传播到文件中。
三、读写数据:
缓冲区支持顺序和随机数据访问,它有一个可以通过get()和put()操作来移动的位置
get(byte[] bytes)gte(byte[] bytes,int offset, int length)gteInt()getLong()....
Java对二进制数据使用高位在前的排序机制while (buffer.hasRemaining()){byte b = buffer.get();...}//通过get(int i) 达到随机访问for (int i = 0; i < buffer.limit(); i++) {byte b = buffer.get(i);}
- 如果需要以低位在前的排序方式处理包含二进制数字的文件
buffer.order(ByteOrder._LITTLE_ENDIAN_);
- 查询缓冲区内当前的字节顺序
buffer.order();
四、结束:在恰当的时机,以及当通道关闭时,会将这些修改写回到文件中
Tips:
- 计算文件的32位的循环冗余校验和(CRC32),
- 用来判断一个文件是否已损坏的校验和,因为文件损坏极有可能导致校验和改变。
- java.util.zip包中包含一个CRC32类

- 方法
- FileInputStream、FileOutputStream、RandomAccessFile都可以获取这个管道
- FileChannel
getChannel()
- FileChannel
文件加锁机制
简介:考虑一下多个同时执行的程序需要修改同一个文件的情形 


**fileLock.close();**
- 释放锁
文件加锁机制是依赖于操作系统的,下面是需要注意的几点:
- 在某些系统中,文件加锁仅仅是建议性的,如果一个应用未能得到锁,它仍旧可以向被另一个应用并发锁定的文件执行写操作。
- 在某些系统中,不能在锁定一个文件的同时将其映射到内存中。
- 文件锁是由整个Java虚拟机持有的。如果有两个程序是由同一个虚拟机启动的(例如Applet和应用程序启动器),那么它们不可能每一个都获得一个在同一个文件上的锁。当调用lock和tryLock方法时,如果虚拟机已经在同一个文件上持有了另一个重叠的锁,那么这两个方法将抛出OverlappingFileLockException。
- 在一些系统中,关闭一个通道会释放由Java虚拟机持有的底层文件上的所有锁。因此,在同一个锁定文件上应避免使用多个通道。
- 在网络文件系统上锁定文件是高度依赖于系统的,因此应该尽量避免
