louzin
6 months ago
15 changed files with 546 additions and 4 deletions
@ -0,0 +1,146 @@
|
||||
# Buffer |
||||
其中Position和Limit的含义取决于Buffer在read还是write模式 |
||||
|
||||
无论何种模式,Capacity含义不变 |
||||
|
||||
Buffer支持的类型 |
||||
- ByteBuffer |
||||
- MappedByteBuffer |
||||
- CharBuffer |
||||
- DoubleBuffer |
||||
- FloatBuffer |
||||
- IntBuffer |
||||
- LongBuffer |
||||
- ShortBuffer |
||||
![img.png](img/img.png) |
||||
## Capacity |
||||
内存块,Buffer的固定值 |
||||
|
||||
只能写入Byte,Long,Char等类型,若Buffer满了需要清除才能继续写数据 |
||||
## Position |
||||
写的时候代表写入数据当前位置,初始位置指向0,最大值为Capacity-1 |
||||
|
||||
读的时候代表读入数据当前位置,初始位置指向0 |
||||
## Limit |
||||
写数据时,Limit表示对Buffer最大写入多少容量,写模式下等于Capacity |
||||
|
||||
读数据时表示还有多少数据可读 |
||||
## 分配与写数据 |
||||
### 创建 |
||||
|
||||
```java |
||||
import java.nio.ByteBuffer; |
||||
import java.nio.CharBuffer; |
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocate(48); |
||||
CharBuffer charBuffer=ByteBuffer.allocate(1024) |
||||
``` |
||||
### 写数据 |
||||
#### Channel |
||||
```java |
||||
int bytesRead = inChannel.read(buf); |
||||
//read into buffer |
||||
``` |
||||
#### put() |
||||
```java |
||||
buf.put(127); |
||||
``` |
||||
### flip() |
||||
切换读写模式 |
||||
|
||||
### 读数据 |
||||
#### Buffer |
||||
```java |
||||
int bytesWrite = inChannel.write(buf); |
||||
``` |
||||
#### get() |
||||
```java |
||||
byte aByte = buf.get(); |
||||
``` |
||||
## 常用方法 |
||||
### rewind() |
||||
position置零,重读buffer数据,limit不变 |
||||
### clear() compact() |
||||
clear直接清除 |
||||
|
||||
compact未读数据可继续读 |
||||
### mark() reset() |
||||
使用mark方法标记buffer中的一个特定position,通过reset()恢复这个position |
||||
## 缓冲区操作 |
||||
### 缓冲区分片 slice() |
||||
在现有buffer缓冲区中切分出一块新区域 |
||||
```java |
||||
public void bufferSlice(){ |
||||
ByteBuffer allocate = ByteBuffer.allocate(10); |
||||
for(int i=0;i<allocate.capacity();i++){ |
||||
allocate.put((byte)i); |
||||
} |
||||
//slice |
||||
allocate.position(3); |
||||
allocate.limit(7); |
||||
ByteBuffer slice = allocate.slice(); |
||||
for(int i=0;i<slice.capacity();i++){ |
||||
slice.put((byte) i); |
||||
} |
||||
// allocate.position(0);//置零 |
||||
// allocate.limit(allocate.capacity());//指向末尾 |
||||
|
||||
while (allocate.hasRemaining()){ |
||||
System.out.print(allocate.get()); |
||||
} |
||||
System.out.println(); |
||||
slice.flip(); |
||||
while (slice.hasRemaining()){ |
||||
System.out.print(slice.get()); |
||||
} |
||||
|
||||
} |
||||
``` |
||||
### 只读缓冲区 asReadOnlyBuffer() |
||||
asReadOnlyBuffer()将任何常规缓冲区变为只读,这个方法会返回一个与原缓冲区完全相同的缓冲区,并与原缓冲区共享数据,不过只可读 |
||||
```java |
||||
public void readOnlyBuffer(){ |
||||
ByteBuffer allocate = ByteBuffer.allocate(10); |
||||
for(int i=0;i<allocate.capacity();i++){ |
||||
allocate.put((byte)i); |
||||
} |
||||
ByteBuffer readOnly=allocate.asReadOnlyBuffer(); |
||||
readOnly.flip(); |
||||
while (readOnly.hasRemaining()){ |
||||
System.out.print(readOnly.get()); |
||||
} |
||||
} |
||||
``` |
||||
若原缓冲区发生变动,只读分区随之变动 |
||||
### 直接缓冲区 allocateDirect() |
||||
加速I/O速度,在使用本方法创建后底层每一次I/O操作之前或之后会尝试避免将缓冲区的内容拷贝到一个中间缓冲区中,或者从一个中间缓冲区中拷贝数据 |
||||
```java |
||||
public void directBuffer() throws IOException { |
||||
RandomAccessFile randomAccessFile = new RandomAccessFile("src/main/resources/bufferreader.txt","rw"); |
||||
RandomAccessFile copy = new RandomAccessFile("src/main/resources/copy.txt","rw"); |
||||
ByteBuffer byteBuffer =ByteBuffer.allocateDirect(1024); |
||||
FileChannel channel = randomAccessFile.getChannel(); |
||||
FileChannel channel1 = copy.getChannel(); |
||||
while (true){ |
||||
byteBuffer.clear(); |
||||
if(channel.read(byteBuffer)==-1){ |
||||
break; |
||||
} |
||||
byteBuffer.flip(); |
||||
channel1.write(byteBuffer); |
||||
} |
||||
} |
||||
``` |
||||
### 内存映射文件I/O |
||||
```java |
||||
static private final int start=0; |
||||
static private final int size=1024; |
||||
public void memBuffer() throws Exception { |
||||
RandomAccessFile randomAccessFile = new RandomAccessFile("src/main/resources/bufferreader.txt","rw"); |
||||
FileChannel fc = randomAccessFile.getChannel(); |
||||
MappedByteBuffer mappedByteBuffer= fc.map(FileChannel.MapMode.READ_WRITE,start,size); |
||||
mappedByteBuffer.put(0,(byte) 97); |
||||
mappedByteBuffer.put(1023,(byte) 122); |
||||
randomAccessFile.close(); |
||||
} |
||||
``` |
After Width: | Height: | Size: 180 KiB |
@ -0,0 +1,78 @@
|
||||
package com.louzin.niodemo.bufferdemo; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import java.io.FileNotFoundException; |
||||
import java.io.IOException; |
||||
import java.io.RandomAccessFile; |
||||
import java.nio.Buffer; |
||||
import java.nio.ByteBuffer; |
||||
import java.nio.MappedByteBuffer; |
||||
import java.nio.channels.FileChannel; |
||||
|
||||
public class buffer3 { |
||||
@Test |
||||
public void bufferSlice(){ |
||||
ByteBuffer allocate = ByteBuffer.allocate(10); |
||||
for(int i=0;i<allocate.capacity();i++){ |
||||
allocate.put((byte)i); |
||||
} |
||||
//slice
|
||||
allocate.position(3); |
||||
allocate.limit(7); |
||||
ByteBuffer slice = allocate.slice(); |
||||
for(int i=0;i<slice.capacity();i++){ |
||||
slice.put((byte) i); |
||||
} |
||||
// allocate.position(0);//置零
|
||||
// allocate.limit(allocate.capacity());//指向末尾
|
||||
|
||||
while (allocate.hasRemaining()){ |
||||
System.out.print(allocate.get()); |
||||
} |
||||
System.out.println(); |
||||
slice.flip(); |
||||
while (slice.hasRemaining()){ |
||||
System.out.print(slice.get()); |
||||
} |
||||
} |
||||
@Test |
||||
public void readOnlyBuffer(){ |
||||
ByteBuffer allocate = ByteBuffer.allocate(10); |
||||
for(int i=0;i<allocate.capacity();i++){ |
||||
allocate.put((byte)i); |
||||
} |
||||
ByteBuffer readOnly=allocate.asReadOnlyBuffer(); |
||||
readOnly.flip(); |
||||
while (readOnly.hasRemaining()){ |
||||
System.out.print(readOnly.get()); |
||||
} |
||||
} |
||||
@Test |
||||
public void directBuffer() throws IOException { |
||||
RandomAccessFile randomAccessFile = new RandomAccessFile("src/main/resources/bufferreader.txt","rw"); |
||||
RandomAccessFile copy = new RandomAccessFile("src/main/resources/copy.txt","rw"); |
||||
ByteBuffer byteBuffer =ByteBuffer.allocateDirect(1024); |
||||
FileChannel channel = randomAccessFile.getChannel(); |
||||
FileChannel channel1 = copy.getChannel(); |
||||
while (true){ |
||||
byteBuffer.clear(); |
||||
if(channel.read(byteBuffer)==-1){ |
||||
break; |
||||
} |
||||
byteBuffer.flip(); |
||||
channel1.write(byteBuffer); |
||||
} |
||||
} |
||||
|
||||
static private final int start=0; |
||||
static private final int size=1024; |
||||
public void memBuffer() throws Exception { |
||||
RandomAccessFile randomAccessFile = new RandomAccessFile("src/main/resources/bufferreader.txt","rw"); |
||||
FileChannel fc = randomAccessFile.getChannel(); |
||||
MappedByteBuffer mappedByteBuffer= fc.map(FileChannel.MapMode.READ_WRITE,start,size); |
||||
mappedByteBuffer.put(0,(byte) 97); |
||||
mappedByteBuffer.put(1023,(byte) 122); |
||||
randomAccessFile.close(); |
||||
} |
||||
} |
@ -0,0 +1,39 @@
|
||||
package com.louzin.niodemo.bufferdemo; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import java.io.FileNotFoundException; |
||||
import java.io.IOException; |
||||
import java.io.RandomAccessFile; |
||||
import java.nio.ByteBuffer; |
||||
import java.nio.IntBuffer; |
||||
import java.nio.channels.FileChannel; |
||||
|
||||
public class buffertest { |
||||
@Test |
||||
public void buffer01() throws IOException { |
||||
RandomAccessFile randomAccessFile = new RandomAccessFile("src/main/resources/bufferreader.txt", "rw"); |
||||
FileChannel channel = randomAccessFile.getChannel(); |
||||
ByteBuffer allocate = ByteBuffer.allocate(1024); |
||||
int read = channel.read(allocate); |
||||
allocate.flip(); |
||||
while (allocate.hasRemaining()){ |
||||
System.out.print((char) allocate.get()); |
||||
} |
||||
randomAccessFile.close(); |
||||
} |
||||
//intbuffer
|
||||
@Test |
||||
public void buffertest1(){ |
||||
IntBuffer allocate = IntBuffer.allocate(8); |
||||
//write data into buffer
|
||||
for(int i=0;i<8;i++){ |
||||
allocate.put(i); |
||||
} |
||||
allocate.flip(); |
||||
while (allocate.hasRemaining()){ |
||||
System.out.print(allocate.get()); |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,4 +0,0 @@
|
||||
package com.louzin.niodemo.bufferdemo; |
||||
|
||||
public class test { |
||||
} |
@ -0,0 +1,28 @@
|
||||
package com.louzin.niodemo; |
||||
|
||||
import static java.lang.Thread.sleep; |
||||
|
||||
public class demo{ |
||||
public static void main(String[] args) throws InterruptedException { |
||||
Runnable rb=new Data(); |
||||
Thread td =new Thread(rb); |
||||
td.start(); |
||||
while(true){ |
||||
sleep(1000); |
||||
System.out.print(3); |
||||
} |
||||
} |
||||
} |
||||
class Data implements Runnable { |
||||
@Override |
||||
public void run() { |
||||
while(true) { |
||||
try { |
||||
sleep(1000); |
||||
} catch (InterruptedException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
System.out.print("2"); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,30 @@
|
||||
package com.louzin.niodemo; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import java.io.FileNotFoundException; |
||||
import java.io.IOException; |
||||
import java.io.RandomAccessFile; |
||||
import java.nio.ByteBuffer; |
||||
import java.nio.channels.FileChannel; |
||||
import java.nio.charset.StandardCharsets; |
||||
|
||||
public class nioFileChannelTest { |
||||
@Test |
||||
public void testRead() throws IOException { |
||||
RandomAccessFile randomAccessFile = new RandomAccessFile("src/main/resources/mytest.txt","rw"); |
||||
FileChannel fileChannel = randomAccessFile.getChannel(); |
||||
//buffer
|
||||
ByteBuffer allocate = ByteBuffer.allocate(1024); |
||||
fileChannel.read(allocate); |
||||
System.out.println(allocate.position()); |
||||
allocate.put("aac".getBytes(StandardCharsets.UTF_8)); |
||||
System.out.println(allocate.position()); |
||||
allocate.flip(); |
||||
while (allocate.hasRemaining()) |
||||
System.out.print((char) allocate.get()); |
||||
fileChannel.close(); |
||||
allocate.clear(); |
||||
randomAccessFile.close(); |
||||
} |
||||
} |
@ -0,0 +1,14 @@
|
||||
package com.louzin.niodemo.scatterandgather; |
||||
//scatter 分散:将数据分散到多个buffer中
|
||||
//ByteBuffer header = ByteBuffer.allocate(128);
|
||||
//ByteBuffer body=ByteBuffer.allocate(1024);
|
||||
//ByteBuffer[] byteBuffers={header,body};
|
||||
//channel.read(byteBuffers);
|
||||
//
|
||||
//scatter Reads只适合固定消息,不适合动态消息
|
||||
|
||||
//gahter 聚集:将多个buffer的数据发送到同一个channel
|
||||
//ByteBuffer header = ByteBuffer.allocate(128);
|
||||
//ByteBuffer body=ByteBuffer.allocate(1024);
|
||||
//ByteBuffer[] byteBuffers={header,body};
|
||||
//channel.write(byteBuffers);
|
@ -0,0 +1,39 @@
|
||||
package com.louzin.niodemo.socketnioclienttest; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.InetSocketAddress; |
||||
import java.net.SocketAddress; |
||||
import java.nio.ByteBuffer; |
||||
import java.nio.channels.DatagramChannel; |
||||
import java.nio.charset.StandardCharsets; |
||||
|
||||
//无连接,面向udp,可任意发送和接受数据包
|
||||
//UDP不存在真正意义上的连接
|
||||
//以下的连接是向特定服务器read和write接受和发包
|
||||
public class datagramChannel { |
||||
@Test |
||||
public void datagramChannelTest() throws IOException { |
||||
DatagramChannel open = DatagramChannel.open(); |
||||
open.bind(new InetSocketAddress("www.baidu.com",10086)); |
||||
//receive udp data package
|
||||
ByteBuffer allocate = ByteBuffer.allocate(64); |
||||
allocate.clear(); |
||||
SocketAddress receive = open.receive(allocate); |
||||
//发送数据包
|
||||
//打开同DatagramChannel open
|
||||
//配置发送内容
|
||||
ByteBuffer wrap = ByteBuffer |
||||
.wrap("client send".getBytes(StandardCharsets.UTF_8)); |
||||
//发送数据包
|
||||
open.send(wrap,new InetSocketAddress("",80)); |
||||
//read和write只有在connect后才能使用,不然NotYetConnectException
|
||||
//read未接受到包时PortUnreachableException
|
||||
open.connect(new InetSocketAddress("",10086)); |
||||
int readSize = open.read(allocate); |
||||
open.write(wrap); |
||||
|
||||
|
||||
} |
||||
} |
@ -0,0 +1,89 @@
|
||||
package com.louzin.niodemo.socketnioclienttest; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.InetAddress; |
||||
import java.net.InetSocketAddress; |
||||
import java.net.SocketAddress; |
||||
import java.nio.Buffer; |
||||
import java.nio.ByteBuffer; |
||||
import java.nio.channels.ByteChannel; |
||||
import java.nio.channels.DatagramChannel; |
||||
import java.nio.charset.Charset; |
||||
import java.nio.charset.StandardCharsets; |
||||
|
||||
public class datagramChannel2 { |
||||
//send
|
||||
@Test |
||||
public void sendDataPackage() throws IOException, InterruptedException { |
||||
//get Channel
|
||||
DatagramChannel open = DatagramChannel.open(); |
||||
InetSocketAddress l = new InetSocketAddress("localhost", 9999); |
||||
open.configureBlocking(false); |
||||
//send
|
||||
while (true){ |
||||
open.send(ByteBuffer.wrap("UDPUDPUDP".getBytes(StandardCharsets.UTF_8)),l); |
||||
System.out.println("发送完成"); |
||||
Thread.sleep(1000); |
||||
} |
||||
} |
||||
@Test |
||||
public void receiveDataPackage() throws IOException { |
||||
DatagramChannel open = DatagramChannel.open(); |
||||
open.bind(new InetSocketAddress("localhost",9999)); |
||||
//通过buffer读取
|
||||
ByteBuffer allocate = ByteBuffer.allocate(1024); |
||||
while (true){ |
||||
allocate.clear(); |
||||
SocketAddress receive = open.receive(allocate); |
||||
allocate.flip(); |
||||
System.out.println(receive.toString()); |
||||
//发送时含有中文,编码处理
|
||||
System.out.println(Charset.forName("UTF-8").decode(allocate)); |
||||
|
||||
} |
||||
} |
||||
@Test() |
||||
public void readWriteTest() throws IOException { |
||||
DatagramChannel open = DatagramChannel.open(); |
||||
open.bind(new InetSocketAddress(9999)); |
||||
open.connect(new InetSocketAddress("localhost",9999)); |
||||
open.write(ByteBuffer.wrap("发送12332111111!!!".getBytes(StandardCharsets.UTF_8))); |
||||
ByteBuffer allocate = ByteBuffer.allocate(64); |
||||
while (true){ |
||||
allocate.clear(); |
||||
open.read(allocate); |
||||
allocate.flip(); |
||||
System.out.println(Charset.forName("UTF-8").decode(allocate)); |
||||
|
||||
} |
||||
} |
||||
@Test |
||||
public void writeTest() throws IOException, InterruptedException { |
||||
DatagramChannel open = DatagramChannel.open(); |
||||
open.bind(new InetSocketAddress("localhost",9990)); |
||||
open.connect(new InetSocketAddress("localhost",9990)); |
||||
while (true){ |
||||
open.write(ByteBuffer.wrap("发送!!!".getBytes(StandardCharsets.UTF_8))); |
||||
System.out.println("发送成功"); |
||||
Thread.sleep(1000); |
||||
} |
||||
|
||||
} |
||||
@Test |
||||
public void readTest() throws IOException, InterruptedException { |
||||
DatagramChannel open = DatagramChannel.open(); |
||||
open.connect(new InetSocketAddress("localhost",9990)); |
||||
ByteBuffer allocate = ByteBuffer.allocate(64); |
||||
while (true){ |
||||
Thread.sleep(500); |
||||
System.out.println("等待写入"); |
||||
allocate.clear(); |
||||
open.read(allocate); |
||||
allocate.flip(); |
||||
System.out.println(Charset.forName("UTF-8").decode(allocate)); |
||||
|
||||
} |
||||
} |
||||
} |
@ -0,0 +1,28 @@
|
||||
package com.louzin.niodemo.socketnioclienttest; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.InetSocketAddress; |
||||
import java.nio.ByteBuffer; |
||||
import java.nio.channels.SocketChannel; |
||||
|
||||
public class socketClientDemo { |
||||
@Test |
||||
public void createChannel() throws IOException { |
||||
//创建SocketChannel
|
||||
SocketChannel open = SocketChannel |
||||
.open(new InetSocketAddress( |
||||
"www.baidu.com", 80)); |
||||
//第二种方法
|
||||
// SocketChannel open1 = SocketChannel.open();
|
||||
// open1.connect(new InetSocketAddress(
|
||||
// "www.baidu.com", 80));
|
||||
//设置阻塞/非阻塞模式
|
||||
open.configureBlocking(false); |
||||
ByteBuffer allocate = ByteBuffer.allocate(16); |
||||
open.read(allocate); |
||||
open.close(); |
||||
System.out.println("ReadOver"); |
||||
} |
||||
} |
@ -0,0 +1,41 @@
|
||||
package com.louzin.niodemo.socketniotest; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.InetSocketAddress; |
||||
import java.nio.ByteBuffer; |
||||
import java.nio.channels.ServerSocketChannel; |
||||
import java.nio.channels.SocketChannel; |
||||
import java.nio.charset.StandardCharsets; |
||||
|
||||
public class ServerSocketChannelDemo { |
||||
@Test |
||||
public void createPort() throws IOException, InterruptedException { |
||||
int port = 8888; |
||||
ByteBuffer wrap = ByteBuffer.wrap("hello socket".getBytes(StandardCharsets.UTF_8)); |
||||
//ServerSocketChannel
|
||||
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); |
||||
//ServerSocketChannel未实现绑定,所以需要手动绑定
|
||||
//得到socket对象,完成对其绑定
|
||||
serverSocketChannel.socket().bind(new InetSocketAddress(port)); |
||||
//非阻塞模式运行
|
||||
serverSocketChannel.configureBlocking(false); |
||||
//监听是否有新连接传入
|
||||
while (true){ |
||||
//返回值若为null,则无传入
|
||||
//若为阻塞模式,则会卡到这里直到连接建立
|
||||
SocketChannel accept = serverSocketChannel.accept(); |
||||
System.out.println("等待连接!"); |
||||
if(accept==null){ |
||||
System.out.println("未发现新连接!"); |
||||
Thread.sleep(2000); |
||||
}else { |
||||
System.out.println("发现新连接!!"+accept.socket().getRemoteSocketAddress()); |
||||
wrap.rewind();//指针0
|
||||
accept.write(wrap); |
||||
accept.close(); |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue