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');//IndexOutOfBoundsExceptionrw.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) {//创建一个BufferByteBuffer buffer = ByteBuffer.allocate(64);for (int i = 0; i < 64; i++) {buffer.put((byte) i);}buffer.flip();//将buffer转成只读BufferByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();System.out.println(readOnlyBuffer.getClass());//class java.nio.HeapByteBufferRwhile (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 {//前面一直用文件通道,这里用ServerSocketChannelServerSocketChannel 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和limitArrays.stream(byteBuffers).map(buffer -> "position=" + buffer.position() + ",limit=" + buffer.limit()).forEach(System.out::println);Arrays.asList(byteBuffers).forEach(buffer -> buffer.flip());//将buffer数据写入到fileChannellong l1 = 0;while (l1 < messageLength) {long l2 = socketChannel.write(byteBuffers);l1 += l2;}//将所有的buffer进行clearArrays.asList(byteBuffers).forEach(buffer -> buffer.clear());}}}
}