io:面向流。阻塞式IO,将他的输入输出看成水流
NIO:面向缓冲区,非阻塞式,将他的通道看成铁路,缓冲区拿数据,底层是数组
package test;
import java.nio.ByteBuffer;
//缓冲区,除了boolean类型都有对象的缓冲区
//如bytebuffer
//通过allocate分配缓冲区的大小
//通过put或者get存放数据
//caoacity:容量。position:位置,limit:界限
//mark用来标记当前状态。通过reset回到那个状态
//isremaining看看缓冲区是否还有剩余的数据
class test {
public static void main(String[] args) {
String s="abcd";
ByteBuffer byt=ByteBuffer.allocate(1024);
System.out.println("--allocate--");
System.out.println(byt.capacity());
System.out.println(byt.position());
System.out.println(byt.limit());
byt.put(s.getBytes());//存放
System.out.println("--put--");
System.out.println(byt.capacity());
System.out.println(byt.position());
System.out.println(byt.limit());//1024
byt.flip();//切换读取模式
System.out.println("--flip--");
System.out.println(byt.capacity());
System.out.println(byt.position());//0
System.out.println(byt.limit());//4
byte[] bt=new byte[byt.limit()];
byt.get(bt);//get读取缓冲区
System.out.println(new String(bt,0,bt.length));
System.out.println("--get--");
System.out.println(byt.capacity());
System.out.println(byt.position());//4
System.out.println(byt.limit());//4
byt.rewind();//position归0
System.out.println("--rewind--");
System.out.println(byt.capacity());
System.out.println(byt.position());//0
System.out.println(byt.limit());//4
byt.clear();//清空缓存区,但是数据还在。处于被遗忘状态
System.out.println("--clear--");
System.out.println(byt.capacity());
System.out.println(byt.position());//0
System.out.println(byt.limit());//1024
}
}
非直接缓冲区:通过allocate(底层代码在堆内存开辟数组)分配缓冲区,将缓冲区建立在jvm内存中
直接缓冲区:通过allocatedirect(在操作系统上)直接分配,将缓冲区建立在物理内存上,可以挺高效率。不安全,消耗大,写入文件我们管不了
channel通道:源节点与目标节点的连接,channel本身不存储数据,需要配合缓存区存储。
通过getchannel获取通道如
fileoutputstream/fileoutputstream
网络IO
socket/serversocket/datagramsocket
JDK7中NIO2中可以通过open方法或者files类的newbytechannel方法开通道。
//通道直接缓冲区(内存映射文件)
FileChannel in = FileChannel.open(Paths.get("1.jpg"),StandardOpenOption.READ);
FileChannel out = FileChannel.open(Paths.get("2.jpg"),StandardOpenOption.WRITE,StandardOpenOption.READ);
//内存映射文件
MappedByteBuffer map = in.map(MapMode.READ_ONLY, 0, in.size());
MappedByteBuffer map2 = out.map(MapMode.READ_WRITE, 0,in.size());
//直接对缓冲区进行读写操作
byte[] b=new byte[1024];
map.get(b);
map2.put(b);
in.close();
out.close();
//通道间数据传输(直接缓冲区)
FileChannel in = FileChannel.open(Paths.get("1.jpg"),StandardOpenOption.READ);
FileChannel out = FileChannel.open(Paths.get("2.jpg"),StandardOpenOption.WRITE,StandardOpenOption.READ);
in.transferTo(0, in.size(), out);
in.close();
out.close();
阻塞nio读写文件
class client {
public static void main(String[] args) throws IOException {
SocketChannel open = SocketChannel.open(new InetSocketAddress("127.0.0.1", 12345));//打开通道
FileChannel open2 = FileChannel.open(Paths.get("1.txt"), StandardOpenOption.READ);//打开复制文件通道
ByteBuffer allocate = ByteBuffer.allocate(1024);//建立缓冲区
while(open2.read(allocate)!=-1){
allocate.flip();//打开读取模式
open.write(allocate);
allocate.clear();
}
open.shutdownOutput();
//接受服务器端反馈
int len=0;
while((len=open.read(allocate))!=-1){
allocate.flip();
System.out.println(new String(allocate.array(),0,len));
allocate.clear();
}
open2.close();
open.close();
}}
class server{
public static void main(String[] args) throws IOException {
ServerSocketChannel open = ServerSocketChannel.open();//打开网络通道
//选择要存储的地方
FileChannel open2 = FileChannel.open(Paths.get("2.txt"), StandardOpenOption.WRITE,StandardOpenOption.CREATE);
//与端口号绑定
open.bind(new InetSocketAddress( 12345));
SocketChannel accept = open.accept();
ByteBuffer allocate = ByteBuffer.allocate(1024);
while(accept.read(allocate)!=-1){
allocate.flip();
open2.write(allocate);
allocate.clear();
}
allocate.put("已经收到".getBytes());
allocate.flip();
accept.write(allocate);
}
}
利用选择器进行非阻塞NIO
class server{
public static void main(String[] args) throws IOException {
ServerSocketChannel open = ServerSocketChannel.open();//打开网络通道
open.configureBlocking(false);
//与端口号绑定
open.bind(new InetSocketAddress(12345));
//获取选择器
Selector selector = Selector.open();
//将通道注册到选择器上
open.register(selector, SelectionKey.OP_ACCEPT);
//轮询式获取选择器上准备就绪事件
while(selector.select()>0){
//获取当前选择器中所有注册的选择键
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while(iterator.hasNext()){
//获取准备就绪的事件
SelectionKey sk = iterator.next();
//判断什么事件准备就绪
if(sk.isAcceptable()){
//若接受就绪,客户端获取连接
SocketChannel accept = open.accept();
//切换非阻塞模式
accept.configureBlocking(false);
//将该通道注册到选择器上
accept.register(selector, SelectionKey.OP_READ);
}else if(sk.isReadable()){
//获取读就绪状态的通道
SocketChannel channel = (SocketChannel)sk.channel();
//读取数据
ByteBuffer allocate = ByteBuffer.allocate(1024);
int len=0;
while((len=channel.read(allocate))!=-1){
allocate.flip();
System.out.printf(new String(allocate.array()),0,len);
allocate.clear();
}
}
}
}
}
}
class client {
public static void main(String[] args) throws IOException {
SocketChannel open = SocketChannel.open(new InetSocketAddress("127.0.0.1",12345));//打开通道
open.configureBlocking(false);//切换成非阻塞模式
//分配缓冲区
ByteBuffer allocate = ByteBuffer.allocate(1024);
//发送数据
allocate.put("你好".getBytes());
allocate.flip();
open.write(allocate);
allocate.clear();
}
}