![](https://img.haomeiwen.com/i8491882/17f3e24f801af8cb.png)
image.png
![](https://img.haomeiwen.com/i8491882/fc08aa0c8db3c800.png)
image.png
public class BasicBuffer {
public static void main(String[] args) {
// 举例说明 Buffer 的使用 (简单说明)
// 创建一个 Buffer, 大小为 5,即可存放5个int
IntBuffer intBuffer = IntBuffer.allocate(5);
// 向 buffer 存放数据
for (int i = 0; i < intBuffer.capacity(); i++) {
intBuffer.put(i * 2);
}
// 如何从buffer读取数据
// 将buffer转换,读写切换
intBuffer.flip();
while (intBuffer.hasRemaining()) {
System.out.println(intBuffer.get());
}
}
}
![](https://img.haomeiwen.com/i8491882/6200fe0c4274c09e.png)
image.png
![](https://img.haomeiwen.com/i8491882/726824cc52173423.png)
image.png
![](https://img.haomeiwen.com/i8491882/02f7a7293aa15f24.png)
image.png
![](https://img.haomeiwen.com/i8491882/71c3772674064e63.png)
image.png
![](https://img.haomeiwen.com/i8491882/d07d8839099dd19d.png)
image.png
![](https://img.haomeiwen.com/i8491882/a672aad3326a1bb3.png)
image.png
![](https://img.haomeiwen.com/i8491882/295f749cbc014272.png)
image.png
![](https://img.haomeiwen.com/i8491882/873001c5cf25cbc3.png)
image.png
![](https://img.haomeiwen.com/i8491882/2a955a612bdda451.png)
image.png
![](https://img.haomeiwen.com/i8491882/bbc2a1dbc24414b2.png)
image.png
![](https://img.haomeiwen.com/i8491882/cf36e1c2c1522144.png)
image.png
![](https://img.haomeiwen.com/i8491882/3f8638c737d4b9cb.png)
image.png
public class NIOFileChannel01 {
public static void main(String[] args) throws IOException {
String str = "hello,尚硅谷";
// 创建一个输出流-> channel
FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\32582\\Desktop\\file01.txt");
// 通过fileOutputStream获取对应的FileChannel
// 这个fileChannel真实类型FileChannelImpl
FileChannel fileChannel = fileOutputStream.getChannel();
// 创建一个缓冲区 ByteBuffer
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
// 将 str 放入到 byteBuffer
byteBuffer.put(str.getBytes());
// 对 byteBuffer 进行 flip
byteBuffer.flip();
// 将 byteBuffer 数据写入到 fileChannel
fileChannel.write(byteBuffer);
fileOutputStream.close();
}
}
![](https://img.haomeiwen.com/i8491882/08a0e872a9b3a6bf.png)
image.png
![](https://img.haomeiwen.com/i8491882/9289ec1f915867d1.png)
image.png
public class NIOFileChannel02 {
public static void main(String[] args) throws IOException {
// 创建文件输入流
File file = new File("C:\\Users\\32582\\Desktop\\file01.txt");
FileInputStream fileInputStream = new FileInputStream(file);
// 通过fileInputStream获取对应的FileChannel
// 这个fileChannel真实类型FileChannelImpl
FileChannel fileChannel = fileInputStream.getChannel();
// 创建一个缓冲区 ByteBuffer
ByteBuffer byteBuffer = ByteBuffer.allocate((int) file.length());
// 将 通道的数据读入到 byteBuffer
fileChannel.read(byteBuffer);
// 将 byteBuffer 的字节数据转成String
System.out.println(new String(byteBuffer.array()));
fileInputStream.close();
}
}
![](https://img.haomeiwen.com/i8491882/8073184fefb10949.png)
image.png
![](https://img.haomeiwen.com/i8491882/e196bf84369ff93d.png)
image.png
public class NIOFileChannel03 {
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = new FileInputStream("1.txt");
FileChannel fileChannel01 = fileInputStream.getChannel();
FileOutputStream fileOutputStream = new FileOutputStream("2.txt");
FileChannel fileChannel02 = fileOutputStream.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(512);
while (true) {
// 这里有一个重要的操作,一定不要忘了
byteBuffer.clear(); // 清空 buffer
int read = fileChannel01.read(byteBuffer);
System.out.println("read = " + read);
if (read == -1) { // 表示读完
break;
}
// 将 buffer中的数据写入到fileChannel02 -- 2.txt
byteBuffer.flip();
fileChannel02.write(byteBuffer);
}
// 关闭相关的流
fileInputStream.close();
fileOutputStream.close();
}
}
![](https://img.haomeiwen.com/i8491882/3bd2992eaa2bd5c3.png)
image.png
public class NIOFileChannel04 {
public static void main(String[] args) throws IOException {
// 创建相关流
FileInputStream fileInputStream = new FileInputStream("C:\\Users\\32582\\Desktop\\a.jpg");
FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\32582\\Desktop\\a2.jpg");
// 获取各个流对应的 fileChannel
FileChannel sourceChannel = fileInputStream.getChannel();
FileChannel destChannel = fileOutputStream.getChannel();
// 使用 transferForm 完成拷贝
destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
// 关闭相关通道和流
sourceChannel.close();
destChannel.close();
fileInputStream.close();
fileOutputStream.close();
}
}
![](https://img.haomeiwen.com/i8491882/d65cc1153a4817b4.png)
image.png
public class NIOByteBufferPutGet {
public static void main(String[] args) {
// 创建一个Buffer
ByteBuffer buffer = ByteBuffer.allocate(64);
// 类型化方式放入数据
buffer.putInt(100);
buffer.putLong(9);
buffer.putChar('尚');
buffer.putShort((short) 4);
// 取出
buffer.flip();
System.out.println();
System.out.println(buffer.getShort());
System.out.println(buffer.getInt());
System.out.println(buffer.getLong());
System.out.println(buffer.getLong());
}
}
public class ReadOnlyBuffer {
public static void main(String[] args) {
// 创建一个Buffer
ByteBuffer buffer = ByteBuffer.allocate(64);
for (int i = 0; i < 64; i++) {
buffer.put((byte) i);
}
// 读取
buffer.flip();
// 得到一个只读的buffer
ByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();
System.out.println(readOnlyBuffer.getClass());
// 读取
while (readOnlyBuffer.hasRemaining()) {
System.out.println(readOnlyBuffer.get());
}
readOnlyBuffer.put((byte) 100); // 报异常
}
}
/**
* 说明
* 1 MappedByteBuffer 可以让文件直接在内存(对外内存)修改,操作系统不需要拷贝一次
*/
public class MappedByteBufferTest {
public static void main(String[] args) throws IOException {
RandomAccessFile randomAccessFile = new RandomAccessFile("1.txt", "rw");
// 获取对应的通道
FileChannel channel = randomAccessFile.getChannel();
/*
* 参数1:FileChannel.MapMode.READ_WRITE 使用的读写模式
* 参数2:0:可以直接修改的起始位置
* 参数3:5:是映射到内存的大小(不是索引位置),即将1.txt的多少个字节映射到内存
* 可以直接修改的范围就是0-5
* 实际类型 DirectByteBuffer
*/
MappedByteBuffer mappedByteBuffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 5);
mappedByteBuffer.put(0, (byte) 'H');
mappedByteBuffer.put(3, (byte) '9');
// mappedByteBuffer.put(5, (byte) 'Y');
randomAccessFile.close();
System.out.println("修改成功");
}
}
/**
* Scattering:将数据写入到buffer时,可以采用buffer数组,依次写入【分散】
* Gathering:从buffer读取数据时,可以采用buffer数组,依次读
*/
public class ScatteringAndGatheringTest {
public static void main(String[] args) throws IOException {
// 使用 ServerSocketChannel 和 SocketChannel 网络
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
InetSocketAddress inetSocketAddress = new InetSocketAddress(6666);
// 绑定端口到socket,并启动
serverSocketChannel.socket().bind(inetSocketAddress);
// 创建buffer数组
ByteBuffer[] byteBuffers = new ByteBuffer[2];
byteBuffers[0] = ByteBuffer.allocate(5);
byteBuffers[1] = ByteBuffer.allocate(3);
// 等客户端连接(telnet)
SocketChannel socketChannel = serverSocketChannel.accept();
int messageLength = 8; // 假定从客户端接收8个字节
// 循环读
while (true) {
int byteRead = 0;
while (byteRead < messageLength) {
long l = socketChannel.read(byteBuffers);
byteRead += l;// 累计读取的字节数
System.out.println("byteRead=" + byteRead);
// 使用流打印,看看当前的这个buffer的position和limit
Arrays.stream(byteBuffers)
.map(buffer -> "position=" + buffer.position() + ",limit=" + buffer.limit())
.forEach(System.out::println);
}
// 将所有的buffer进行flip
Arrays.asList(byteBuffers).forEach(ByteBuffer::flip);
// 将数据读出显示到客户端
long byteWrite = 0;
while (byteWrite < messageLength) {
long l = socketChannel.write(byteBuffers);
byteWrite += l;
}
// 将所有的buffer,进行clear
Arrays.asList(byteBuffers).forEach(ByteBuffer::clear);
System.out.println("byteRead=" + byteRead + " byteWrite=" + byteWrite + " messageLength=" + messageLength);
}
}
}
![](https://img.haomeiwen.com/i8491882/898ca57d0144620d.png)
image.png
![](https://img.haomeiwen.com/i8491882/26dd0c4e921d4223.png)
image.png
![](https://img.haomeiwen.com/i8491882/6ac45709e5b055b9.png)
image.png
![](https://img.haomeiwen.com/i8491882/27af931e3d151b16.png)
image.png
![](https://img.haomeiwen.com/i8491882/370f3fedd3a0166d.png)
image.png
![](https://img.haomeiwen.com/i8491882/c6df1e2ea7ebc21c.png)
image.png
![](https://img.haomeiwen.com/i8491882/301422ad7a5d2b7c.png)
image.png
public class NIOServer {
public static void main(String[] args) throws IOException {
// 创建 ServerSocketChannel -> ServerSocket
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// 获得一个Selector 对象
Selector selector = Selector.open();
// 绑定一个端口 6666, 在服务器端监听
serverSocketChannel.socket().bind(new InetSocketAddress(6666));
// 设置为非阻塞
serverSocketChannel.configureBlocking(false);
// 把 severSocketChannel 注册到 selector 关心事件 OP_ACCEPT
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
// 循环等待客户端连接
while (true) {
// 这里我们等待1秒,如果没有事件发生,返回
if (selector.select(1000) == 0) { // 没有事件发生
System.out.println("服务器等待1秒,无连接");
continue;
}
// 如果返回的>0,就获取到相关的 selectionKey 集合
// 1 如果返回的>0,表示已经获取到关注的事件
// 2 selector.selectedKeys() 返回关注事件的集合
// 通过 selectionKeys 反向获取通道
Set<SelectionKey> selectionKeys = selector.selectedKeys();
// 遍历 Set<SelectionKey>, 使用迭代器遍历
Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
while (keyIterator.hasNext()) {
// 获取到 selectionKey
SelectionKey key = keyIterator.next();
// 根据key对应的通道发生的事件做相应处理
if (key.isAcceptable()) { // 如果是 OP_ACCEPT,有新的客户端连接
// 该客户端生成一个 StockChannel
SocketChannel socketChannel = serverSocketChannel.accept();
System.out.println("客户端连接成功,生成了一个 socketChannel " + socketChannel.hashCode());
// 将 SocketChannel 设置为非阻塞
socketChannel.configureBlocking(false);
// 将 socketChannel 注册到 selector, 关注事件为 OP_READ, 同时给 socketChannel
// 关联一个 Buffer
socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
}
if (key.isReadable()) { // 发生 OP_READ
// 通过 key 反向获取到对应 channel
SocketChannel channel = (SocketChannel) key.channel();
// 获取到该channel关联的buffer
ByteBuffer buffer = (ByteBuffer) key.attachment();
channel.read(buffer);
System.out.println("from 客户端 " + new String(buffer.array()));
}
// 手动从集合中移除当前的 selectionKey, 防止重复操作
keyIterator.remove();
}
}
}
}
public class NIOClient {
public static void main(String[] args) throws IOException {
// 得到一个网络通道
SocketChannel socketChannel = SocketChannel.open();
// 设置非阻塞
socketChannel.configureBlocking(false);
// 提供服务器端ip和port
InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 6666);
// 连接服务器
if (!socketChannel.connect(inetSocketAddress)) {
while (!socketChannel.finishConnect()) {
System.out.println("因为连接需要时间,客户端不会阻塞,可以做其他工作");
}
}
// 如果连接成功,就发送数据
String str = "hello, 尚硅谷";
// warps a byte array into a buffer
ByteBuffer buffer = ByteBuffer.wrap(str.getBytes());
// 发送数据,将buffer数据写入channel
socketChannel.write(buffer);
System.in.read();
}
}
![](https://img.haomeiwen.com/i8491882/3a58c1558dd47c01.png)
image.png
![](https://img.haomeiwen.com/i8491882/556f86d3de7ca01f.png)
image.png
![](https://img.haomeiwen.com/i8491882/e983f251eb289d81.png)
image.png
![](https://img.haomeiwen.com/i8491882/f40694d32bcde091.png)
image.png
网友评论