简介
NIO的所有类都被放在java.nio包或其子包下。
特点
- 面向块的I/O:传统JavaIO是面向流的I/O。流I/O一次处理一个字节。NIO中引入了缓冲区(Buffer)的概念,缓冲区作为传输数据的基本单位块,所有对数据的操作都是基于将数据移进/移出缓冲区而来。
- 非阻塞的I/O + 就绪性选择:非阻塞I/O则允许线程在有数据的时候处理数据,没有数据的时候干点别的,提高了资源利用率。就绪性选择通常是建立在非阻塞的基础上,并且更进一步,它把检查哪些I/O请求的数据准备好这个任务交给了底层操作系统,操作系统会去查看并返回结果集合,这样我们只需要关心那些准备好进行操作的IO通道。
- 文件锁定和内存映射文件等操作系统特性:内存映射利用虚拟内存技术提供对文件的高速缓存,使读取磁盘文件就像从内存中读取一样高效,但是却不会有内存泄漏的危险,因为在内存中不会存在文件的完整拷贝。
Buffer
简介
Buffer有Byte、Short、Int、Long、Float、DoubleBuffer六个类别,起缓存作用。
Buffer有四个基本属性:
1、capacity 容量,buffer能够容纳的最大元素数目,在Buffer创建时设定并不能更改
2、limit buffer中有效位置数目,不能对超过limit中的区域进行读写。
3、position 下一个读或者写的位置
4、mark 用于记忆的标志位,配合reset()使用,初始值未设定,调用mark后将当前position设为值
利用Buffer读写数据,通常遵循四个步骤:
获取buffer
把数据写入buffer;
调用flip;
从Buffer中读取数据;
调用buffer.clear()或者buffer.compact()
方法:
获取:
static xxxBuffer allocate(int capacity)//创建容量为capacity的buffer
写入:
void putxxx(xxx f)
void putxxx(int index, xxx f)
void flip()//limit=position,position=0 //方便读取数据
读取:
xxx getFloat()
xxx getFloat(int index)
void clear()//position=0,limit=capacity,方便再次装入数据
其他方法:
int capacity()//获取capacity
boolean hasRemaining()//是否有元素未处理,即position<limit
int limit()
int position()
int remainint()//return limit-position
Channel
Channel用于在字节缓冲区和位于通道另一侧的实体(通常是一个文件或套接字)之间有效地传输数据。。与缓冲区不同,通道API主要由接口指定。不同的操作系统上通道实现(Channel Implementation)会有根本性的差异,所以通道API仅仅描述了可以做什么。因此很自然地,通道实现经常使用操作系统的本地代码。通道接口允许您以一种受控且可移植的方式来访问底层的I/O服务。
Channel和流的区别
- Channel可以将整个文件或文件的一部分映射成为buffer
- Channel是一个对象,可以通过它读取和写入数据。拿 NIO 与原来的 I/O 做个比较,通道就像是流。所有数据都通过 Buffer 对象来处理。您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区。同样,您不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。
- 既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。
- 通道可以异步地读写。
- 通道中的数据总是要先读到一个 Buffer,或者总是要从一个 Buffer 中写入。
- FileChannel对象是线程安全(thread-safe)的。
常用的Channel
FileChannel:从文件中读写数据。
DatagramChannel:能通过UDP读写网络中的数据。
SocketChannel:能通过TCP读写网络中的数据。
ServerSocketChannel:可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。
使用
- 所有Channel都应该使用传统的流来构建,如:FileChannel channel=fileInputStream.getChannel().
RandomAccessFile也有这个方法,Channel是可读还是可写,取决于它的打开方式r/rw - Channel常用方法:
将文件映射到内存
ByteBuffer buffer=channel.map(FileChannel.MapMode.READ_ONLY,0,file.length);
写到Channel
channel.write(buffer)
读取到buffer
channel.read(byteBuffer)
移动Channel的positon
channel.position(long length)
字符集和Charset
JAVA默认使用Unicode编码,但是有些操作系统不适用Unicode。
方法
获取支持的所有字符集
SortedMap<String,Charset>=Charset.availableCharsets()
获取charset实例
charset=Charset.forName("gbk")
编解码
charbuffer=charset.decode(bytebuffer)
bytebuffer=charset.encoce(charbuffer/string)
文件锁(进程级)
FileLock支持文件锁定功能。在FileChannel中提供lock和tryLock方法来获得FileLock对象。
fileLock可以只锁定文件的一部分。
lock(long position , long size,boolean shared)//阻塞式
tryLock(long position ,long sized,boolean shared)//非阻塞
FileLock lock=fileChannel.tryLock();
dosomething.....
lock.release();
文件锁是JVM持有的,如果两个进程运行在同一个JVM,则他们不能对同一个文件加锁。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。