/**
* MappedByteBuffer作用:可以让文件直接在内存(堆外的内存)中进行修改,而操作系统不需要拷贝一次,有点像DirectByteBuffer
* 实际上DirectByteBuffer也是MappedByteBuffer作用的子类。
*
* 注意:执行完代码后,IDEA的文件并没有及时改变,但是如果我们在外面打开文件,他的确是发生改变的。
*/
public class MappedByteBufferTest {
public static void main(String[] args) throws IOException {
RandomAccessFile randomAccess = new RandomAccessFile("file1.txt", "rw");
FileChannel fileChannel = randomAccess.getChannel();
//0-5范围内容可以直接在内存操作
MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 5);
mappedByteBuffer.put(0, (byte) 'b');
mappedByteBuffer.put(1, (byte) 'b');
randomAccess.close();
}
}
至于如何将修改同步到磁盘的文件当中,是由OS系统完成的,我们不需要管.
文件也有锁
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
public class NioTest10 {
public static void main(String[] args) throws Exception{
RandomAccessFile randomAccessFile = new RandomAccessFile("NIOTest10.txt", "rw");
FileChannel channel = randomAccessFile.getChannel();
FileLock fileLock = channel.lock(3, 6, true);
System.out.println("valid:" + fileLock.isValid());
System.out.println("lock type:" + fileLock.isShared());
fileLock.release();
randomAccessFile.close();
}
}
Scaterring 撒开,分散,将来自于一个Channel的数据分散到多个Buffer当中,一个满了就用下一个,可以实现数据的分门别类.
这样就省去了解析的时间,比如一个消息有三个部分,第一部分是头信息,第二部分是协议信息,第三部分是消息体.
可以吧这三个消息分别放到不同的Buffer当中,
Gatering 把多个汇总成一个,将要写到Channel的数据,
/**
* Scattering:在将数据写入到buffer中时,可以采用buffer数组,依次写入,一个buffer满了就写下一个。
* Gatering:在将数据读出到buffer中时,可以采用buffer数组,依次读入,一个buffer满了就读下一个。
*/
/**
* 使用方式:打开cmd telnet locakhost 8899
* 连接后可以输入字符串了
*/
public class ScatteringAndGatherIng {
public static void main(String[] args) throws IOException {
ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
InetSocketAddress address=new InetSocketAddress(8899);
serverSocketChannel.socket().bind(address);
int messageLength=2+3+5;
ByteBuffer[] byteBuffers=new ByteBuffer[3];
byteBuffers[0]=ByteBuffer.allocate(2);
byteBuffers[1]=ByteBuffer.allocate(3);
byteBuffers[2]=ByteBuffer.allocate(5);
SocketChannel socketChannel=serverSocketChannel.accept();
while (true){
int byteRead=0;
//接受客户端写入的的字符串
while(byteRead<messageLength){
long r=socketChannel.read(byteBuffers);
byteRead+=r;
System.out.println("byteRead:"+byteRead);
//通过流打印
Arrays.asList(byteBuffers).stream().
map(buffer -> "postiton:"+ buffer.position() +",limit:"+buffer.limit()).
forEach(System.out::println);
}
//将所有buffer都flip。
Arrays.asList(byteBuffers).
forEach(buffer -> {
buffer.flip();
});
//将数据读出回显到客户端
long byteWrite=0;
while (byteWrite < messageLength) {
long r=socketChannel.write(byteBuffers);
byteWrite+=r;
}
//将所有buffer都clear
Arrays.asList(byteBuffers).
forEach(buffer -> {
buffer.clear();
});
System.out.println("byteRead:"+byteRead+",byteWrite:"+byteWrite+",messageLength:"+messageLength);
}
}
}