1.举例
package org.example.demo;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.RandomAccess;
/**
* MappedByteBuffer可以让文件直接在内存中(堆外内存)修改,操作系统不需要拷贝一次
* @author hrui
* @date 2024/7/28 15:22
*/
public class MappedByteBufferTest {
public static void main(String[] args) throws IOException {
RandomAccessFile rw = new RandomAccessFile("D:\\1.txt", "rw");
//获取对应的通道
FileChannel channel = rw.getChannel();
/**
* 参数1: FileChannel.MapMode.READ_WRITE,使用读写模式
* 参数2: 0,可以直接修改的起始位置
* 参数3: 5,映射到内存的大小(不是索引位置,即将1.txt映射到内存的字节个数)
* 映射多少个字节,映射多少个字节就修改多少个字节
*/
MappedByteBuffer mappedByteBuffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 5);
mappedByteBuffer.put(0, (byte) 'H');
mappedByteBuffer.put(3, (byte) '9');
//mappedByteBuffer.put(5, (byte) '9');//IndexOutOfBoundsException
rw.close();
}
}
2.举例 将Buffer转成只读Buffer
package org.example.demo;
import java.nio.ByteBuffer;
/**
* 将Buffer转成只读Buffer
* @author hrui
* @date 2024/7/28 14:32
*/
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转成只读Buffer
ByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();
System.out.println(readOnlyBuffer.getClass());//class java.nio.HeapByteBufferR
while (readOnlyBuffer.hasRemaining()) {
System.out.println(readOnlyBuffer.get());
}
readOnlyBuffer.put((byte) 100);//抛出ReadOnlyBufferException
}
}
3.举例 NIO提供了MappedByteBuffer,可以让文件直接在内存(堆外的内存)中进行修改
而如何同步到文件由NIO来完成
package org.example.demo;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.RandomAccess;
/**
* MappedByteBuffer可以让文件直接在内存中(堆外内存)修改,操作系统不需要拷贝一次
* @author hrui
* @date 2024/7/28 15:22
*/
public class MappedByteBufferTest {
public static void main(String[] args) throws IOException {
RandomAccessFile rw = new RandomAccessFile("D:\\1.txt", "rw");
//获取对应的通道
FileChannel channel = rw.getChannel();
/**
* 参数1: FileChannel.MapMode.READ_WRITE,使用读写模式
* 参数2: 0,可以直接修改的起始位置
* 参数3: 5,映射到内存的大小(不是索引位置,即将1.txt映射到内存的字节个数)
* 映射多少个字节,映射多少个字节就修改多少个字节
*/
MappedByteBuffer mappedByteBuffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 5);
mappedByteBuffer.put(0, (byte) 'H');
mappedByteBuffer.put(3, (byte) '9');
rw.close();
}
}
4.举例,前面都是通过一个Buffer完成的,NIO还支持通过多个Buffer(即Buffer数组)完成读写操作
即Scattering(分散)和Gathering(聚合)
package org.example.demo;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
/**
* Scattering:(分散)将数据写入到Buffer时,可以采用Buffer数组,分散的将数据写入到各个Buffer中
* Gathering:(聚集)将数据从Buffer读取到数据时,可以采用Buffer数组,聚集的将数据从多个Buffer中读取
* @author hrui
* @date 2024/7/28 15:36
*/
public class ScatteringAndGatheringTest {
public static void main(String[] args) throws IOException {
//前面一直用文件通道,这里用ServerSocketChannel
ServerSocketChannel open = ServerSocketChannel.open();
InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 9999);
//绑定端口到Socket,并启动
open.socket().bind(inetSocketAddress);
//创建Buffer数组
ByteBuffer[] byteBuffers = new ByteBuffer[2];
byteBuffers[0] = ByteBuffer.allocate(5);
byteBuffers[1] = ByteBuffer.allocate(3);
//等待客户端连接
System.out.println("等待客户端连接...");
SocketChannel socketChannel = open.accept();
int messageLength = 8;
while (true) {
int read = 0;
while (read < messageLength) {
long l = socketChannel.read(byteBuffers);
read += l;
System.out.println("read=" + read);
//使用流打印,看看每个buffer的position和limit
Arrays.stream(byteBuffers).map(buffer -> "position=" + buffer.position() + ",limit=" + buffer.limit()).forEach(System.out::println);
Arrays.asList(byteBuffers).forEach(buffer -> buffer.flip());
//将buffer数据写入到fileChannel
long l1 = 0;
while (l1 < messageLength) {
long l2 = socketChannel.write(byteBuffers);
l1 += l2;
}
//将所有的buffer进行clear
Arrays.asList(byteBuffers).forEach(buffer -> buffer.clear());
}
}
}
}