java io和nio_JAVA的io流和nio有什么区别?

1,NIO vs BIO

2,NIO的工作模式

NIO有三大核心:

1. Channel(通道)

2. Buffer(缓冲区)

3. Selector(选择器) NIO基于Channel和Buffer进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。

Channel提供了从文件,网络读取数据的通道,但是读或写数据,都必须经过Buffer,如下图所示:

Selector用于监听多个通道的事件,从而达到一个线程监听多个客户端通道的效果。即多路复用技术。

1,NIO vs BIO

BIONIO

流(单向)通道Channel(双向)

数组Buffer

阻塞式非阻塞式

2,NIO的工作模式

NIO有三大核心:

1. Channel(通道)

2. Buffer(缓冲区)

3. Selector(选择器) NIO基于Channel和Buffer进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。

Channel提供了从文件,网络读取数据的通道,但是读或写数据,都必须经过Buffer,如下图所示:

Selector用于监听多个通道的事件,从而达到一个线程监听多个客户端通道的效果。即多路复用技术。

3,文件IO的核心API

3.1 Buffer

3.2 Channel

4,文件IO-编程实战

4.1 采用NIO写文件

@Test

public void writeTest() throws Exception {

//1.创建一个输出流

FileOutputStream fileOutputStream = new FileOutputStream("nio.txt");

//2.通过输出流创建一个通道

FileChannel channel = fileOutputStream.getChannel();

//3.创建一个缓冲区

ByteBuffer buffer = ByteBuffer.allocate(1024);

//4.将字节数据写入到缓冲区中buffer.put("hello,nio".getBytes());

//5.注意,此时缓冲区的指针已经随着放入的数据而发生偏移

//所以,需要重置

buffer.flip();

//6.将缓冲区的数据写入通道,通道负责将数据写入到文件中channel.write(buffer);

//7.关闭资源fileOutputStream.close();

}

4.2 采用NIO读文件

@Test

public void readTest() throws IOException {

//1.创建一个输入流

FileInputStream fileInputStream = new FileInputStream("nio.txt");

//2.通过输入流创建一个通道

FileChannel channel = fileInputStream.getChannel();

//3.创建一个缓冲区

ByteBuffer buffer = ByteBuffer.allocate(1024);

//4.从通道中读取数据,并写入到缓冲区中channel.read(buffer);

//5.输出读取到的数据

System.out.println(new String(buffer.array()));

//6.关闭资源fileInputStream.close();

}

4.3 完成文件的复制

@Test

public void copyTest() throws Exception{

//1.创建输入流和输出流

FileInputStream fileInputStream = new FileInputStream("nio.txt"); FileOutputStream fileOutputStream = new FileOutputStream("nio_copy.txt");

//2.通过流创建两个通道

FileChannel source = fileInputStream.getChannel(); FileChannel target = fileOutputStream.getChannel();

//3.通过通道实现快速拷贝

//target.transferFrom(source,0,source.size()); source.transferTo(0,source.size(),target);

//4.关闭资源

fileOutputStream.close(); fileInputStream.close();

}

5,网络IO

5.1 工作模式

NIO的主要应用场景就是网络IO,网络IO的通道是非阻塞式的,基于事件驱动,适合于大量连接,但数据交换量不大的情况。 比如即时通讯。

包括4个关键API

1. Selector

2. SelectionKey

3. ServerSocketChannel

4. SocketChannel

5.2 Selector

通过选择器可以检测多个注册的通道是否有事件发生,如果有事件发生,便捕获事件并进行处理。

这样就可以达到一个线程处理多个客户端连接的效果

5.3 SelectionKey

代表Selector和网络通道的注册关系。

1. OP_ACCEPT:表示有新的网络连接可以accept

2. OP_CONNECT:表示连接已经建立

3. OP_READ:表示读操作

4. OP_WRITE:表示写操作

5.4 ServerSocketChannel

服务端监听新的客户端socket连接

5.5 SocketChannel

网络通道,负责具体的读写操作。 将缓存区的数据写入通道,或者从通道将数据读到缓冲区。

6,编码实战

6.1 目标

实现客户端和服务端之间的网络通信

客户端程序

/**

* @author huangguizhao

*/

public class NIOClient {

public static void main(String[] args) throws IOException {

//1.创建一个网络通道

SocketChannel channel = SocketChannel.open();

//2.设置该通道为非阻塞channel.configureBlocking(false);

//3.设置连接的服务端IP及端口

InetSocketAddress address = new InetSocketAddress("127.0.0.1",6666);

//4.连接服务器

//如果连接不上服务器,则尝试重复连接

if(!channel.connect(address)){//没连接成功

while (!channel.finishConnect()){

//等待连接,体现NIO的非阻塞优势

System.out.println("客户端在连接服务端的同时,还可以做其他的事");

}

}

//5.创建一个缓存区,用于存放发送的数据

ByteBuffer buffer = ByteBuffer.wrap("hello,nio server".getBytes());

//6.发送数据channel.write(buffer);

//7.避免服务端程序结束,设置阻塞System.in.read();

}

}

6.2 服务端程序

/**

* @author huangguizhao

*/

public class NIOServer {

public static void main(String[] args) throws IOException {

//1.创建ServerSocketChannel对象

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

//2.绑定监听的端口号

serverSocketChannel.bind(new InetSocketAddress(6666));

//3.设置为非阻塞式

serverSocketChannel.configureBlocking(false);

//4.创建一个Selector对象

Selector selector = Selector.open();

//5.把ServerSocketChannel对象注册给Selector对象

//同时关注连接事件

serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

//6.Selector开始监控while (true){

//每隔1秒钟查看是否可处理的事件if(selector.select(1000) == 0){

//非阻塞的体现

System.out.println("当前没有事件需要处理,服务器可以做点其他事");

continue;

}

//获取需要处理的事件,因为可能存在多个客户端的事件需要处理,所以返回的是集合Iterator keyIterator = selector.selectedKeys().iterator();

//开始循环处理事件

while (keyIterator.hasNext()){

//获取到事件

SelectionKey key = keyIterator.next();

//根据不同的事件,做不同的处理if(key.isAcceptable()){

System.out.println("有新的客户端连接......... ");

SocketChannel socketChannel = serverSocketChannel.accept(); socketChannel.configureBlocking(false);

//将当前的channel注册到Selector上,监听可读事件

socketChannel.register(selector,SelectionKey.OP_READ);

}

if(key.isReadable()){

SocketChannel socketChannel = (SocketChannel) key.channel();

//创建一个缓存区对象

ByteBuffer buffer = ByteBuffer.allocate(1024);

//将通道的数据读取到缓冲区socketChannel.read(buffer);

//输出结果

System.out.println(new String(buffer.array()));

}

//关键一步

//需要将当前的key移除,避免重复处理

keyIterator.remove();

}

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值