一、读写概念
1.Channel 读写概念 二、FileChannel 文件读写方法
1.写文件2.读文件3.复制文件4.修改文件 三、ServerSocketChannel Buffer 聚集和分散
1.启动一个ServerSocketChannel2.通过Telnet连接:telnet 127.0.0.1 7800 按【CTRL+]】组合键进入发送数据状态
一、读写概念 1.Channel 读写概念在UTF-8编码中: 一个中文字符等于三个字节,一个中文标点符号占三个字节 一个英文字符等于一个字节,一个英文标点占一个字节 一个数字符号等于一个字节
read ---> 从通道读取数据写入 Buffer write ---> 将 Buffer 数据写入通道二、FileChannel 文件读写方法 1.写文件
public static void saveFile() throws IOException {
String str = "Hello Moon";
String filePath = "save.txt";
//创建一个输出流->channel
FileOutputStream fileOutputStream = new FileOutputStream(filePath);
//通过FileOutputStream获取 对应的 FileChannel
//这个FileChannel 真实类型是 FileChannelImpl
FileChannel fileChannel = fileOutputStream.getChannel();
//创建一个缓冲区Buffer
ByteBuffer buffer = ByteBuffer.allocate(1024);
//将Str 放入 Buffer
buffer.put(str.getBytes(StandardCharsets.UTF_8));
//对ByteBuffer 进行反转 flip
buffer.flip();
//将buffer数据写入通道fileChannel
fileChannel.write(buffer);
//关闭流
fileOutputStream.close();
}
2.读文件
public static void readFile() throws IOException {
//创建文件输入流
File file = new File("save.txt");
FileInputStream fileInputStream = new FileInputStream(file);
//获取FileChannel
FileChannel fileChannel = fileInputStream.getChannel();
//创建字节缓冲区
ByteBuffer buffer = ByteBuffer.allocate((int)file.length());
//将通道内数据读到缓冲区
fileChannel.read(buffer);
//将buffer转换为string
System.out.println(new String(buffer.array()));
fileInputStream.close();
}
3.复制文件
public static void copyFile() throws IOException {
//1.创建一个输出流->channel
FileInputStream fileInputStream = new FileInputStream("save.txt");
//2.获取输入流通道
FileChannel readChannel = fileInputStream.getChannel();
//3.创建输出流
FileOutputStream fileOutputStream = new FileOutputStream("copy.txt");
//4.获取输出流通道
FileChannel writeChannel = fileOutputStream.getChannel();
//5.定义 512 字节的缓冲区
ByteBuffer buffer = ByteBuffer.allocate(512);
while (-1 != readChannel.read(buffer)){
//切换读写状态并输出
buffer.flip();
writeChannel.write(buffer);
//重置buffer 否则position与limit一致时 缓冲区填满无法在增加新数据
buffer.clear();
}
fileInputStream.close();
fileOutputStream.close();
}
4.修改文件
public static void modifyFile() throws IOException {
RandomAccessFile randomAccessFile = new RandomAccessFile("save.txt","rw");
//获取通道
FileChannel fileChannel = randomAccessFile.getChannel();
//定义编辑区域
MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE,0,5);
mappedByteBuffer.put(0,(byte)'h');
fileChannel.close();
}
三、ServerSocketChannel Buffer 聚集和分散
1.启动一个ServerSocketChannel
package com.example.netty.channel;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
public class NIOServerSocketChannel {
public static void main(String[] args) throws IOException {
//使用 ServerSocketChannel 和 SocketChannel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
InetSocketAddress inetSocketAddress = new InetSocketAddress(7800);
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();
//假定从客户端读取 8 字节
int messageLength = 8;
//循环读取
while (true){
long byteRead = 0;
while (byteRead < messageLength){
long read = socketChannel.read(byteBuffers);
byteRead += read;
//打印buffer标志
Arrays.stream(byteBuffers).forEach(buffer->{
System.out.println("position:" + buffer.position() + " limit:" + buffer.limit());
});
}
//读写切换
Arrays.stream(byteBuffers).forEach(buffer->{
buffer.flip();
});
//将数据读出显示到客户端
long byteWrite = 0;
while (byteWrite < messageLength){
long write = socketChannel.write(byteBuffers);
byteWrite += write;
}
//清空
Arrays.stream(byteBuffers).forEach(buffer->{
buffer.clear();
});
//打印读写情况
System.out.println("byteRead:" + byteRead + " byteWrite:" + byteWrite);
}
}
}
2.通过Telnet连接:telnet 127.0.0.1 7800 按【CTRL+]】组合键进入发送数据状态
第一次发送 6 个字节发现,缓冲区数组未写满,相当于阻塞在此处
继续发送两个字节过来
第二次直接发送 8 个字节发现,程序正常下行



