在学习NIO时,ByteBuffer、Channel、Selector三个组件是必须了解的。前面我们说到ByteBuffer是作为缓冲区进行数据的存放或者获取。通常我们需要进行flip翻转操作,但是这个在Netty中,有一个更为强大的类可以替代ByteBuf,其不需要进行翻转,也可以进行读写的双向操作。要将数据打包到缓冲区中,通常需要使用通道,而通道作为传输数据的载体,也即它可以使数据从一端到另一端,因此就必须进行了解。
Channel中,我们也看到其子类有很多,通常都是用于读写操作的。其中ByteChannel可以进行读写操作,也即可以进行双向操作。
操作过程:首先创建流对象,有了流对象获取通道,然后准备好写入或者读入通道的bytebuffer信息,使用通道写入或者读入。写入或者读入之后,不要忘记关闭通道、关闭流。这里介绍简单的读写操作,更为详细的可以去参考jdk的api。
1.进行写操作
代码语言:javascript复制/**
* 进行channel的学习:
* nio中buffer、channel、selector三个组件,其中buffer提供了读写操作的条件(缓冲区),而channel提供通道,
* 而selector则是多路复用的技术
* channel通道:用来传输数据的通道
* 我们先来看FileChannel:主要是读取、写入、映射和操作文件的通道,该通道永远是阻塞的操作
* 先看写操作 int write(ByteBuffer src);
*/
@Slf4j
public class ChannelWriteTest {
public static void main(String[] args) throws Exception {
//从通道的当前位置开始写入
fileChannelTest1();
System.out.println("================");
//从remaining写入通道
fileChannelTest2();
System.out.println("================");
//write方法具有同步性
fileChennelTest3();
}
//write方法具有同步性
private static void fileChennelTest3() throws InterruptedException, IOException {
//fileChannel中的write方法的同步性
FileOutputStream fos = new FileOutputStream(new File("test2.txt"));
FileChannel fileChannel = fos.getChannel();
//启动两个线程
for (int i = 0; i < 10; i ) {
Thread thread1 = new Thread() {
@Override
public void run() {
ByteBuffer buffer = ByteBuffer.wrap("学无止境rn".getBytes());
try {
fileChannel.write(buffer);
} catch (IOException e) {
log.error("写入数据失败:{}" e.getMessage());
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
ByteBuffer buffer = ByteBuffer.wrap("山高人为峰rn".getBytes());
try {
fileChannel.write(buffer);
} catch (IOException e) {
log.error("写入数据失败:{}" e.getMessage());
}
}
};
thread1.start();
thread2.start();
}
Thread.sleep(3000);
fileChannel.close();
fos.close();
}
//从remaining写入通道
private static void fileChannelTest2() throws IOException {
//创建流对象、获取通道,进行字节包装,使用通道进行写入
FileOutputStream fos = new FileOutputStream(new File("test1.txt"));
FileChannel fileChannel = fos.getChannel();
try {
//子节1:abcde
ByteBuffer buffer1 = ByteBuffer.wrap("abcde".getBytes());
//子节2:12345
ByteBuffer buffer2 = ByteBuffer.wrap("12345".getBytes());
//首先写入abcde,此时buffer2的当前位置是1,因此下一个位置是2,同时上界是3,因此2、3位置会放入,因此会将2、3放入到
//abcde中,变成 ab23e,因此同时通道的位置设置当前位置是2,因此下一个位置是3,因此其位置为2 2=4
fileChannel.write(buffer1);
buffer2.position(1);
buffer2.limit(3);
fileChannel.position(2);
fileChannel.write(buffer2);
System.out.println(fileChannel.position());
} catch (Exception e) {
log.error("写入数据失败:{}" e.getMessage());
}
//关闭流、通道
fileChannel.close();
fos.close();
}
//从通道的当前位置开始写入
private static void fileChannelTest1() throws Exception {
//创建流对象
FileOutputStream fos = new FileOutputStream(new File("test.txt"));
//获取通道
FileChannel fileChannel = fos.getChannel();
try {
//将byte包装成byteBuffer,使用fileChannel的write方法将其写入到file中
ByteBuffer buffer = ByteBuffer.wrap("abcde".getBytes());
//写入之前的位置是0
System.out.println("A fileChannel.postion()=" fileChannel.position());
//写入数据
System.out.println("write() 1 返回值:" fileChannel.write(buffer));
//当前位置变成5
System.out.println("B fileChannel.postion()=" fileChannel.position());
//此时的文件通道的位置是2
fileChannel.position(2);
//将其buffer的位置变成0
buffer.rewind();
//然后往文件里面写数据
System.out.println("write() 2 返回值:" fileChannel.write(buffer));
//可以看到文件通道的位置变成了7
System.out.println("C fileChannel.postion()=" fileChannel.position());
} catch (IOException e) {
log.error("写入数据失败:{}" e.getMessage());
}
//关通道、流
fileChannel.close();
fos.close();
}
}
2.进行读操作
代码语言:javascript复制/**
* fileChannel读操作:int read(ByteBuffer dst);
* 将字节序列从此通道的当前位置读入给定的缓冲区的当前位置
* int中返回的值:
* 正数表示从通道的当前位置向bytebuffer缓冲区中读的字节个数
* 0表示从通道中没有读取任何数据
* -1表示到达流的末端
*/
@Slf4j
public class ChannelReadTest {
public static void main(String[] args) throws Exception {
//使用read方法操作
fileChannelTest1();
System.out.println("=======================");
//从通道的当前位置开始读取
fileChannelTest2();
System.out.println("=======================");
//将字节放入ByteBuffer当前位置
fileChannelTest3();
System.out.println("=======================");
fileChannelTest4();
System.out.println("=======================");
//从通道读取的数据大于缓冲区容量
fileChannelTest5();
System.out.println("=======================");
//从通道读取的字节放入缓冲区的remaining空间中
fileChannelTest6();
}
private static void fileChannelTest6() throws IOException {
FileInputStream fis = new FileInputStream(new File("test.txt"));
FileChannel fileChannel = fis.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(100);
byteBuffer.position(1);
byteBuffer.limit(3);
fileChannel.read(byteBuffer);
fileChannel.close();
fis.close();
byteBuffer.rewind();
for (int i = 0; i < byteBuffer.limit(); i ) {
byte eachByte = byteBuffer.get();
if (eachByte == 0) {
System.out.println("空格");
} else {
System.out.println((char) eachByte);
}
}
}
private static void fileChannelTest5() throws IOException {
FileInputStream fis = new FileInputStream(new File("test.txt"));
FileChannel fileChannel = fis.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(3);
System.out.println("A" fileChannel.position());
fileChannel.read(byteBuffer);
System.out.println("B" fileChannel.position());
fileChannel.close();
fis.close();
byteBuffer.rewind();
for (int i = 0; i < byteBuffer.limit(); i ) {
System.out.println((char) byteBuffer.get());
}
}
private static void fileChannelTest4() throws InterruptedException, IOException {
FileInputStream fis = new FileInputStream(new File("test4.txt"));
FileChannel fileChannel = fis.getChannel();
for (int i = 0; i < 1; i ) {
Thread thread1 = new Thread() {
@Override
public void run() {
try {
ByteBuffer byteBuffer = ByteBuffer.allocate(5);
int readLength = fileChannel.read(byteBuffer);
while (readLength != -1) {
byte[] getByte = byteBuffer.array();
System.out.println(new String(getByte, 0, readLength));
byteBuffer.clear();
readLength = fileChannel.read(byteBuffer);
}
} catch (Exception e) {
log.error("写入数据失败:{}" e.getMessage());
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
try {
ByteBuffer byteBuffer = ByteBuffer.allocate(5);
int readLength = fileChannel.read(byteBuffer);
while (readLength != -1) {
byte[] getByte = byteBuffer.array();
System.out.println(new String(getByte, 0, readLength));
byteBuffer.clear();
readLength = fileChannel.read(byteBuffer);
}
} catch (Exception e) {
log.error("写入数据失败:{}" e.getMessage());
}
}
};
thread1.start();
thread2.start();
}
Thread.sleep(3000);
fileChannel.close();
fis.close();
}
private static void fileChannelTest3() throws IOException {
FileInputStream fos = new FileInputStream(new File("test3.txt"));
FileChannel fileChannel = fos.getChannel();
//当前位置为2,因此下一个位置为3
fileChannel.position(2);
//而长度为5,因此打印结果:3 4 5 空格位置 空格位置
ByteBuffer byteBuffer = ByteBuffer.allocate(5);
fileChannel.read(byteBuffer);
byteBuffer.position(3);
//向byteBuffer读入cd
fileChannel.read(byteBuffer);
byte[] getByteArray = byteBuffer.array();
for (int i = 0; i < getByteArray.length; i ) {
if (getByteArray[i] == 0) {
System.out.println(" 空格 ");
} else {
System.out.println((char) getByteArray[i]);
}
}
fileChannel.close();
fos.close();
}
//从通道的当前位置开始读取
private static void fileChannelTest2() throws IOException {
FileInputStream fis = new FileInputStream(new File("test3.txt"));
FileChannel fileChannel = fis.getChannel();
//当前位置为2,因此下一个位置为3
fileChannel.position(2);
//而长度为5,因此打印结果:3 4 5 空格位置 空格位置
ByteBuffer byteBuffer = ByteBuffer.allocate(5);
fileChannel.read(byteBuffer);
byte[] getByteArray = byteBuffer.array();
for (int i = 0; i < getByteArray.length; i ) {
System.out.println((char) getByteArray[i]);
}
fileChannel.close();
fis.close();
}
//使用read方法操作
private static void fileChannelTest1() throws Exception {
FileInputStream fis = new FileInputStream(new File("test3.txt"));
FileChannel fileChannel = fis.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(5);
int readLength = fileChannel.read(byteBuffer);
System.out.println(readLength);
//由于byteBuffer没有remaing剩余空间,因此返回的就是0
readLength = fileChannel.read(byteBuffer);
System.out.println(readLength);
byteBuffer.clear();
readLength = fileChannel.read(byteBuffer);
//到达流的末尾值为-1
System.out.println(readLength);
byteBuffer.clear();
fileChannel.close();
fis.close();
}
}
3.进行批量写操作
代码语言:javascript复制/**
* 进行批量写操作 long write(ByteBuffer[] src)
* 将每个缓冲区的remaining字节序列写入此通道的当前位置
*/
@Slf4j
public class ChannelBatchWriteTest {
public static void main(String[] args) throws Exception {
//进行批量写操作
fileChannelBatchWriteTest();
fileChannelBatchWriteTest2();
fileChannelBatchWriteTest3();
}
private static void fileChannelBatchWriteTest() throws IOException {
FileOutputStream fos = new FileOutputStream(new File("a.txt"));
FileChannel fileChannel = fos.getChannel();
fileChannel.write(ByteBuffer.wrap("123456".getBytes()));
fileChannel.position(3);
ByteBuffer byteBuffer1 = ByteBuffer.wrap("000001".getBytes());
ByteBuffer byteBuffer2 = ByteBuffer.wrap("000002".getBytes());
//将多个单的bytebuffer放入byteBuffers中,再写入
ByteBuffer[] byteBuffers = new ByteBuffer[]{byteBuffer1,byteBuffer2};
fileChannel.write(byteBuffers);
fileChannel.close();
fos.close();
}
private static void fileChannelBatchWriteTest2() throws IOException {
FileOutputStream fos = new FileOutputStream(new File("b.txt"));
FileChannel fileChannel = fos.getChannel();
fileChannel.write(ByteBuffer.wrap("123456".getBytes()));
fileChannel.position(3);
ByteBuffer byteBuffer1 = ByteBuffer.wrap("abcde1".getBytes());
ByteBuffer byteBuffer2 = ByteBuffer.wrap("uxdax2".getBytes());
//将多个单的bytebuffer放入byteBuffers中,再写入
ByteBuffer[] byteBuffers = new ByteBuffer[]{byteBuffer1,byteBuffer2};
byteBuffer1.position(1);
byteBuffer1.limit(3);
byteBuffer2.position(2);
byteBuffer2.limit(4);
fileChannel.write(byteBuffers);
fileChannel.close();
fos.close();
}
//write方法具有同步性
private static void fileChannelBatchWriteTest3() throws InterruptedException, IOException {
//fileChannel中的write方法的同步性
FileOutputStream fos = new FileOutputStream(new File("c.txt"));
FileChannel fileChannel = fos.getChannel();
//启动两个线程
for (int i = 0; i < 10; i ) {
Thread thread1 = new Thread() {
@Override
public void run() {
ByteBuffer buffer1 = ByteBuffer.wrap("学无止境rn".getBytes());
ByteBuffer buffer2 = ByteBuffer.wrap("吾生有崖亦无涯rn".getBytes());
try {
ByteBuffer[] byteBuffers = new ByteBuffer[]{buffer1,buffer2};
fileChannel.write(byteBuffers);
} catch (IOException e) {
log.error("写入数据失败:{}" e.getMessage());
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
ByteBuffer buffer1 = ByteBuffer.wrap("山高人为峰rn".getBytes());
ByteBuffer buffer2 = ByteBuffer.wrap("前行有路rn".getBytes());
ByteBuffer[] byteBuffers = new ByteBuffer[]{buffer1,buffer2};
try {
fileChannel.write(byteBuffers);
} catch (IOException e) {
log.error("写入数据失败:{}" e.getMessage());
}
}
};
thread1.start();
thread2.start();
}
Thread.sleep(3000);
fileChannel.close();
fos.close();
}
}
4.进行批量读操作
代码语言:javascript复制/**
* 进行批量读操作 long read(ByteBuffer[] dsts)
*/
@Slf4j
public class ChannelBatchReadTest {
public static void main(String[] args) throws Exception {
//进行批量读操作
fileChannelBatchReadTest1();
System.out.println("==========");
//从通道的当前位置开始读取
fileChannelBatchReadTet2();
System.out.println("==========");
//进行批量读,将字节放入ByteBuffer当前位置
fileChannelReadBatchTest3();
System.out.println("==========");
//批量读的同步性
fileChannelReadBatchTest4();
//从通道读取的数据大于缓冲区容量
fileChannelBatchReadTest5();
//从通道的字节放入缓冲去的remaining空间中
fileChannelBatchReadTest6();
}
private static void fileChannelBatchReadTest6() throws IOException {
FileInputStream fis = new FileInputStream(new File("test1.txt"));
FileChannel fileChannel = fis.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(7);
byteBuffer.position(1);
byteBuffer.limit(3);
ByteBuffer byteBuffer1 = ByteBuffer.allocate(7);
byteBuffer.position(2);
byteBuffer.limit(4);
ByteBuffer[] byteBuffers = new ByteBuffer[]{byteBuffer, byteBuffer1};
fileChannel.read(byteBuffers);
fileChannel.close();
fis.close();
byteBuffer.rewind();
byteBuffer1.rewind();
for (int i = 0; i < byteBuffers.length; i ) {
ByteBuffer byteBuffer2 = byteBuffers[i];
byte[] getByte = byteBuffer2.array();
for (int j = 0; j < getByte.length; j ) {
if (getByte[j] == 0) {
System.out.println("空格");
} else {
System.out.println((char) getByte[j]);
}
System.out.println();
}
}
}
private static void fileChannelBatchReadTest5() throws IOException {
FileInputStream fis = new FileInputStream(new File("test1.txt"));
FileChannel fileChannel = fis.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(2);
ByteBuffer byteBuffer1 = ByteBuffer.allocate(2);
ByteBuffer[] byteBuffers = new ByteBuffer[]{byteBuffer, byteBuffer1};
System.out.println("A " fileChannel.position());
long readLength = fileChannel.read(byteBuffers);
System.out.println("B " fileChannel.position() "readLength=" readLength);
fileChannel.close();
fis.close();
byteBuffer.rewind();
byteBuffer1.rewind();
byteBuffer.position(1);
for (int i = 0; i < byteBuffers.length; i ) {
byte[] getByte = byteBuffers[i].array();
for (int k = 0; k < getByte.length; k ) {
System.out.print((char) getByte[k]);
}
System.out.println();
}
}
private static void fileChannelReadBatchTest4() throws Exception {
FileInputStream fis = new FileInputStream(new File("d.txt"));
FileChannel fileChannel = fis.getChannel();
for (int i = 0; i < 10; i ) {
Thread thread1 = new Thread() {
@Override
public void run() {
try {
ByteBuffer byteBuffer = ByteBuffer.allocate(8);
ByteBuffer byteBuffer1 = ByteBuffer.allocate(8);
ByteBuffer[] byteBuffers = new ByteBuffer[]{byteBuffer, byteBuffer1};
long readLength = fileChannel.read(byteBuffers);
while (readLength != -1) {
synchronized (ChannelBatchReadTest.class) {
for (int j = 0; j < byteBuffers.length; j ) {
byte[] getByte = byteBuffers[j].array();
for (int k = 0; k < getByte.length; k ) {
System.out.println((char) getByte[k]);
}
}
}
byteBuffer.clear();
byteBuffer1.clear();
readLength = fileChannel.read(byteBuffers);
}
} catch (Exception e) {
log.error("写入数据失败:{}" e.getMessage());
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
try {
ByteBuffer byteBuffer = ByteBuffer.allocate(8);
ByteBuffer byteBuffer1 = ByteBuffer.allocate(8);
ByteBuffer[] byteBuffers = new ByteBuffer[]{byteBuffer, byteBuffer1};
long readLength = fileChannel.read(byteBuffers);
while (readLength != -1) {
synchronized (ChannelBatchReadTest.class) {
for (int j = 0; j < byteBuffers.length; j ) {
byte[] getByte = byteBuffers[j].array();
for (int k = 0; k < getByte.length; k ) {
System.out.println((char) getByte[k]);
}
}
}
byteBuffer.clear();
byteBuffer1.clear();
readLength = fileChannel.read(byteBuffers);
}
} catch (Exception e) {
log.error("写入数据失败:{}" e.getMessage());
}
}
};
thread1.start();
thread2.start();
}
Thread.sleep(3000);
fileChannel.close();
fis.close();
}
private static void fileChannelReadBatchTest3() throws IOException {
FileInputStream fis = new FileInputStream(new File("test1.txt"));
FileChannel fileChannel = fis.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(2);
ByteBuffer byteBuffer1 = ByteBuffer.allocate(2);
ByteBuffer[] byteBuffers = new ByteBuffer[]{byteBuffer, byteBuffer1};
byteBuffer.position(1);
fileChannel.read(byteBuffers);
for (int i = 0; i < byteBuffers.length; i ) {
byte[] getByte = byteBuffers[i].array();
for (int j = 0; j < getByte.length; j ) {
if (getByte[j] == 0) {
System.out.println("空格");
} else {
System.out.println((char) getByte[j]);
}
System.out.println();
}
fileChannel.close();
fis.close();
}
}
private static void fileChannelBatchReadTet2() throws IOException {
FileInputStream fis = new FileInputStream(new File("test1.txt"));
FileChannel fileChannel = fis.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(2);
ByteBuffer byteBuffer1 = ByteBuffer.allocate(2);
ByteBuffer[] byteBuffers = new ByteBuffer[]{byteBuffer, byteBuffer1};
fileChannel.read(byteBuffers);
for (int i = 0; i < byteBuffers.length; i ) {
byte[] getByte = byteBuffers[i].array();
for (int j = 0; j < getByte.length; j ) {
System.out.println((char) getByte[j]);
}
System.out.println();
}
fileChannel.close();
fis.close();
}
private static void fileChannelBatchReadTest1() throws IOException {
FileInputStream fis = new FileInputStream(new File("test1.txt"));
FileChannel fileChannel = fis.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(2);
ByteBuffer byteBuffer1 = ByteBuffer.allocate(2);
ByteBuffer[] byteBuffers = new ByteBuffer[]{byteBuffer, byteBuffer1};
long readLength = fileChannel.read(byteBuffers);
System.out.println(readLength);
byteBuffer.clear();
byteBuffer1.clear();
readLength = fileChannel.read(byteBuffers);
System.out.println(readLength);
byteBuffer.clear();
byteBuffer1.clear();
readLength = fileChannel.read(byteBuffers);
System.out.println(readLength);
byteBuffer.clear();
byteBuffer1.clear();
readLength = fileChannel.read(byteBuffers);
System.out.println(readLength);
byteBuffer.clear();
byteBuffer1.clear();
fileChannel.close();
fis.close();
}
}
5.进行部分批量写操作
代码语言:javascript复制/**
* 进行部分批量写操作 long write(ByteBuffer[] srcs,int offset,int length)
* 以指定缓冲数组的offset下标开始,向后使用length个字节缓冲区,
* 再将每个缓冲区的remaining剩余字节子序列写入此通道的当前位置
*/
public class ChannelPartBatchWriteTest {
public static void main(String[] args) throws Exception {
fileChannelPartBatchWriteTest1();
fileChannelPartBatchWriteTest2();
}
private static void fileChannelPartBatchWriteTest1() throws IOException {
FileOutputStream fos = new FileOutputStream(new File("test.txt"));
FileChannel fileChannel = fos.getChannel();
ByteBuffer byteBuffer = ByteBuffer.wrap("abcde".getBytes());
ByteBuffer byteBuffer1 = ByteBuffer.wrap("12345".getBytes());
ByteBuffer[] byteBuffers = new ByteBuffer[]{byteBuffer,byteBuffer1};
fileChannel.write(ByteBuffer.wrap("QSDXXX".getBytes()));
fileChannel.position(2);
fileChannel.write(byteBuffers,0,2);
fileChannel.close();
fos.close();
}
private static void fileChannelPartBatchWriteTest2() throws IOException {
FileOutputStream fos = new FileOutputStream(new File("test.txt"));
FileChannel fileChannel = fos.getChannel();
ByteBuffer byteBuffer = ByteBuffer.wrap("abcde".getBytes());
ByteBuffer byteBuffer1 = ByteBuffer.wrap("12345".getBytes());
byteBuffer1.position(1);
byteBuffer1.limit(3);
ByteBuffer byteBuffer3 = ByteBuffer.wrap("dwsrdf".getBytes());
byteBuffer3.position(2);
byteBuffer3.limit(4);
ByteBuffer[] byteBuffers = new ByteBuffer[]{byteBuffer,byteBuffer1,byteBuffer3};
fileChannel.write(byteBuffers,1,2);
fileChannel.position(2);
fileChannel.write(byteBuffers,0,2);
fileChannel.close();
fos.close();
}
}
6.进行部分批量读操作
代码语言:javascript复制/**
* 进行批量读操作 long read(ByteBuffer[] dsts,int offset,int length)
*/
public class ChannelPartBatchReadTest {
public static void main(String[] args) throws Exception{
fileChannelPartBatchReadTest1();
System.out.println("===============");
fileChannelPartBatchReadTest2();
}
private static void fileChannelPartBatchReadTest1() throws IOException {
FileInputStream fis = new FileInputStream(new File("e.txt"));
FileChannel fileChannel = fis.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(2);
ByteBuffer byteBuffer1 = ByteBuffer.allocate(2);
ByteBuffer[] byteBuffers = new ByteBuffer[]{byteBuffer, byteBuffer1};
long readLength = fileChannel.read(byteBuffers,0,2);
System.out.println("readLength=" readLength);
byteBuffer.clear();
byteBuffer1.clear();
readLength = fileChannel.read(byteBuffers,0,2);
System.out.println("readLength=" readLength);
byteBuffer.clear();
byteBuffer1.clear();
readLength = fileChannel.read(byteBuffers,0,2);
System.out.println("readLength=" readLength);
byteBuffer.clear();
byteBuffer1.clear();
fileChannel.close();
fis.close();
}
private static void fileChannelPartBatchReadTest2() throws IOException {
FileInputStream fis = new FileInputStream(new File("e.txt"));
FileChannel fileChannel = fis.getChannel();
fileChannel.position(2);
ByteBuffer byteBuffer = ByteBuffer.allocate(2);
ByteBuffer byteBuffer1 = ByteBuffer.allocate(2);
ByteBuffer[] byteBuffers = new ByteBuffer[]{byteBuffer, byteBuffer1};
fileChannel.read(byteBuffers,0,2);
for (int i = 0; i < byteBuffers.length; i ) {
byte[] getByte = byteBuffers[i].array();
for (int k = 0; k < getByte.length; k ) {
System.out.print((char) getByte[k]);
}
System.out.println();
}
fileChannel.close();
fis.close();
}
}
今天就介绍到这里,下一篇我们学习多路复用必备组件Selector。