package cn.tedu.buffer;
import java.nio.ByteBuffer;
public class ByteBufferDemo {
public static void main(String[] args) {
// 表示给底层的字节数组来指定大小
// 缓冲区在给定之后,长度就不能改变了
ByteBuffer buffer =
ByteBuffer.allocate(10);
// 添加数据
buffer.put("abc".getBytes());
buffer.put((byte) 0);
buffer.put("def".getBytes());
// 将position挪动
// buffer.position(0);
// 获取元素
// 获取的是一个字节
// byte b = buffer.get();
// System.out.println(b);
// byte b2 = buffer.get();
// System.out.println(b2);
// 遍历
// 将limit挪到position的位置上
// 将position归零
// buffer.limit(buffer.position());
// buffer.position(0);
// 上述两部操作称之为翻转缓冲区
// 等价于
buffer.flip();
// while(buffer.position() < buffer.limit()){
// 等价
while(buffer.hasRemaining()){
byte b = buffer.get();
System.out.println(b);
}
}
}
package cn.tedu.buffer;
import java.nio.ByteBuffer;
public class ByteBufferDemo2 {
public static void main(String[] args) {
// 适合于数据未知的场景
// ByteBuffer buffer = ByteBuffer.allocate();
// 数据已知
// ByteBuffer buffer =
// ByteBuffer.wrap("hello big2002".getBytes());
// System.out.println(buffer.position());
ByteBuffer buffer = ByteBuffer.allocate(10);
buffer.put("hello".getBytes());
// 获取缓冲区底层的字节数组
byte[] data = buffer.array();
// System.out.println(new String(data, 0,
// buffer.position()));
buffer.flip();
System.out.println(new String(data, 0,
buffer.limit()));
}
}
@Test
public void readFile() throws Exception {
// 创建RandomAccessFile对象。指定模式为读写模式
RandomAccessFile raf = new RandomAccessFile("F:\\a.txt", "rw");
// 获取FileChannel对象
FileChannel fc = raf.getChannel();
// 创建缓冲区用于存储数据
ByteBuffer buffer = ByteBuffer.allocate(10);
// 记录读取的字节个数
int len;
// 读取数据
while ((len = fc.read(buffer)) != -1) {
System.out.println(new String(buffer.array(), 0, len));
buffer.flip();
}
// 关流
raf.close();
}
@Test
public void writeFile() throws Exception {
// 创建RandomAccessFile对象。指定模式为读写模式
RandomAccessFile raf = new RandomAccessFile("F:\\test.txt", "rw");
// 获取FileChannel对象
FileChannel fc = raf.getChannel();
// 创建缓冲区,并且将数据放入缓冲区
ByteBuffer src = ByteBuffer.wrap("hello".getBytes());
// 利用通道写出数据
fc.write(src);
// 关流
raf.close();
}
@Test
public void copyFile() throws Exception {
// 创建流对象指向对应的文件
FileInputStream in = new FileInputStream("F:\\a.txt");
FileOutputStream out = new FileOutputStream("E:\\a.txt");
// 获取FileChannel对象
FileChannel src = in.getChannel();
FileChannel dest = out.getChannel();
// 准备缓冲区
ByteBuffer buffer = ByteBuffer.allocate(10);
// 读取数据,将读取到的数据写出
while (src.read(buffer) != -1) {
buffer.flip();
dest.write(buffer);
buffer.clear();
}
// 关流
in.close();
out.close();
}
@Test
public void send() throws IOException {
// 开启通道
DatagramChannel dc = DatagramChannel.open();
// 准备数据
ByteBuffer buffer = ByteBuffer.wrap("hello".getBytes());
// 发送数据
dc.send(buffer, new InetSocketAddress("localhost", 8090));
// 关闭通道
dc.close();
}
@Test
public void recieve() throws IOException {
// 开启通道
DatagramChannel dc = DatagramChannel.open();
// 绑定连接地址和端口号
dc.socket().bind(new InetSocketAddress(8090));
// 准备缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 接收数据
dc.receive(buffer);
System.out.println(new String(buffer.array(), 0, buffer.position()));
// 关闭通道
dc.close();
}
@Test
public void client() throws IOException {
// 开启客户端通道
SocketChannel sc = SocketChannel.open();
// 可以手动设置为非阻塞模式
sc.configureBlocking(false);
// 发起连接
sc.connect(new InetSocketAddress("localhost", 8090));
// 由于是非阻塞的,所以连接不一定建立了,所以要判断连接是否建立
while (!sc.isConnected())
// 如果连接没有建立,则试图重新建立连接
sc.finishConnect();
// 写出数据
sc.write(ByteBuffer.wrap("hello".getBytes()));
// 关闭通道
sc.close();
}
@Test
public void server() throws IOException {
// 开启服务器端通道
ServerSocketChannel ssc = ServerSocketChannel.open();
// 绑定要监听的端口
ssc.socket().bind(new InetSocketAddress(8090));
// 手动设置为非阻塞
ssc.configureBlocking(false);
// 获取连接过来的通道
SocketChannel sc = ssc.accept();
// 判断连接是否真正建立
while (sc == null)
// 如果没有建立则重新获取建立
sc = ssc.accept();
// 准备缓冲区用于存储数据
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 读取数据
sc.read(buffer);
System.out.println(new String(buffer.array(), 0, buffer.position()));
// 关闭通道
ssc.close();
}
作用:针对通道的指定事件来进行选择
Selector在使用的时候针对非阻塞通道进行操作
package cn.tedu.selector;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
public class Client {
public static void main(String[] args) throws IOException {
SocketChannel sc = SocketChannel.open();
sc.connect(new InetSocketAddress("localhost",8090));
sc.write(ByteBuffer.wrap("hello server".getBytes()));
//读取数据
ByteBuffer buffer = ByteBuffer.allocate(1024);
sc.read(buffer);
System.out.println(
new String(buffer.array(),0,buffer.position()));
}
}
package cn.tedu.selector;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
public class Srever {
public static void main(String[] args) throws IOException {
//开启服务器通道
ServerSocketChannel ssc = ServerSocketChannel.open();
//设置非阻塞
ssc.configureBlocking(false);
//绑定端口
ssc.bind(new InetSocketAddress(8090));
//开启选择器
Selector selc = Selector.open();
//将通道注册到选择器上
ssc.register(selc, SelectionKey.OP_ACCEPT);
//模拟:服务器开启之后不关闭
while(true){
//随着运行时间的延长,接收到的请求会越来越多
//需要针对这些请求来进行选择,将能触发时间的请求留下
//将不能触发事件的请求过滤掉
selc.select();
//选完之后能够留下来的请求都是有用的请求
//connect/read/write
//获取请求的事件类型
Set<SelectionKey> set = selc.selectedKeys();
//需要针对请求的不同类型类进行分门别类的处理
Iterator<SelectionKey> it = set.iterator();
while(it.hasNext()){
SelectionKey key = it.next();
//触发服务器的accept操作 - 说明客户端一定调用了connect方法
if (key.isAcceptable()){
//从事件中获取通道
ServerSocketChannel sscx = (ServerSocketChannel) key.channel();
//接收连接
SocketChannel sc = sscx.accept();
sc.configureBlocking(false);
//根据需求确定,如果需要读操作,那么就给READ
//如果需要写操作,那就给WRITE
//如果存在多个register,那么后边的会覆盖前边的
sc.register(selc,
// SelectionKey.OP_READ + SelectionKey.OP_WRITE);
// SelectionKey.OP_READ | SelectionKey.OP_WRITE);
SelectionKey.OP_READ ^ SelectionKey.OP_WRITE);
}
if (key.isReadable()){
SocketChannel sc = (SocketChannel)key.channel();
//读数据
ByteBuffer buffer = ByteBuffer.allocate(1024);
sc.read(buffer);
System.out.println(new String(buffer.array(),0,buffer.position()));
//读取完成之后,需要将READ事件从通道身上移除掉
//key.interestOps() 获取到所有事件
sc.register(selc,
key.interestOps() - SelectionKey.OP_READ);
// key.interestOps() ^ SelectionKey.OP_READ);
}
if (key.isWritable()){
SocketChannel sc = (SocketChannel) key.channel();
sc.write(ByteBuffer.wrap("收到数据啦~~".getBytes()));
sc.register(selc,
key.interestOps() - SelectionKey.OP_WRITE);
}
//处理完成之后,需要将这一大类时间移除掉
it.remove();
}
}
}
}