1.简介
通道(Channel):表示IO源与目标打开的连接。Channel不能直接访问数据,需要和Buffer进行交互。
2.通道的主要实现类
java.nio.channels.Channel接口
FileChannel
SocketChannel
ServerSocketChannel
DatagramChannel
3.获取通道
1.java针对支持通道的类提供了getChannel方法
本地IO:
FileInputStream,FileOutputStram
RandomAccessFile
网络IO:
TCP:Socket,ServerSocket
UDP:DataGramSocket
2.提供了静态方法open()
3.Files工具类的newByteChannel()
4.实例
package test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import org.junit.jupiter.api.Test;
public class NIO {
@Test
public void test1() throws Exception {
FileInputStream in = new FileInputStream("panda.jpg");
FileOutputStream out = new FileOutputStream("copy.jpg");
//获取通道
FileChannel inchannel = in.getChannel();
FileChannel outchannel = out.getChannel();
//指定缓冲区大小
ByteBuffer buf = ByteBuffer.allocate(1024);
//把数据写入缓冲区
while(inchannel.read(buf)!=-1) {
buf.flip();//切换成读模式
//将缓冲区的数据写入通道
outchannel.write(buf);
buf.clear();
}
outchannel.close();
inchannel.close();
out.close();
in.close();
}
//使用直接缓冲区完成文件复制
@Test
public void test2() throws IOException {
FileChannel inChannel = FileChannel.open(Paths.get("panda.jpg"),
StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("copy2.jpg"),
StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE);
//内存映射文件
MappedByteBuffer inMap = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outMap = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
//直接对缓冲区进行数据的读写
byte [] dest = new byte[inMap.limit()];
inMap.get(dest);
outMap.put(dest);
inChannel.close();
outChannel.close();
}
}
5.分散和聚集
分散:从Channel中读取的数据分散到多个Buffer中(按顺序一次填满每一个缓冲区)
聚集:从对个Buffer中得到数据聚集到Channel(按顺序写入)
package test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import org.junit.jupiter.api.Test;
public class NIO {
@Test
public void test1() throws Exception {
FileInputStream in = new FileInputStream("panda.jpg");
FileOutputStream out = new FileOutputStream("copy.jpg");
//获取通道
FileChannel inchannel = in.getChannel();
FileChannel outchannel = out.getChannel();
//指定缓冲区大小
ByteBuffer buf = ByteBuffer.allocate(1024);
//把数据写入缓冲区
while(inchannel.read(buf)!=-1) {
buf.flip();//切换成读模式
//将缓冲区的数据写入通道
outchannel.write(buf);
buf.clear();
}
outchannel.close();
inchannel.close();
out.close();
in.close();
}
//使用直接缓冲区完成文件复制
@Test
public void test2() throws IOException {
FileChannel inChannel = FileChannel.open(Paths.get("panda.jpg"),
StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("copy2.jpg"),
StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE);
//内存映射文件
MappedByteBuffer inMap = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outMap = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
//直接对缓冲区进行数据的读写
byte [] dest = new byte[inMap.limit()];
inMap.get(dest);
outMap.put(dest);
inChannel.close();
outChannel.close();
}
@Test
public void test3() throws Exception {
RandomAccessFile ranf1 = new RandomAccessFile("A0A0A0MRZ8.txt", "rw");
FileChannel fc1 = ranf1.getChannel();
ByteBuffer buf1 = ByteBuffer.allocate(100);
ByteBuffer buf2 = ByteBuffer.allocate(1024);
//分散读取
ByteBuffer [] bufs = {buf1,buf2};
fc1.read(bufs);
for (ByteBuffer byteBuffer : bufs) {
byteBuffer.flip();
}
System.out.println(new String (bufs[0].array(),0,bufs[0].limit()));
System.out.println(new String (bufs[1].array(),0,bufs[1].limit()));
//聚集写入
RandomAccessFile ranf2 = new RandomAccessFile("COPY.txt", "rw");
FileChannel fc2 = ranf2.getChannel();
fc2.write(bufs);
}
}