一、通道(Channel): 用于源节点与目标节点的连接。在Java NIO中负责缓冲区中数据的传输。Channel本身不存储数据,因此需要配合和缓冲区进行传输。
二、通道的主要实现类
- java.nio.channels.Channel 接口:
- FileChannel
- SocketChannel
- SeverSocketChannel
- DatagramChannel
三、获取通道
1.Java针对支持通道的类提供了getChannel()方法
-
本地IO:
-
FileInputStream/FileOutputStram
-
RandomAccessFile
-
网络IO:
-
Socket
-
ServerSocket
-
DatagramSocket
2.在jdk1.7中的NIO.2针对各个通道提供了静态方法open()
3.在jdk1.7中的NIO.2的Files工具类的newByteChannel()
四、通道之间的数据传输
- transferFrom()
- transferTo()
五、分散(Scatter)与聚集(Getter)
- 分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区中
- 聚集写入(Gathering Writes):将多个缓冲区中的数据聚集到通道中
六、字符集:Charset
- 编码:将字符串转换成字节数组
- 解码:将字节数组转换成字符串
public class TestChannel {
//1.利用通道完成文件的复制(非直接缓冲区)
@Test
public void test1() {
FileInputStream fis= null;
FileOutputStream fos= null;
FileChannel inchannel = null;
FileChannel outchannel = null;
try {
fis = new FileInputStream("背景图.jpg");
fos = new FileOutputStream("背景图1.jpg");
//① 获取通道
inchannel = fis.getChannel();
outchannel = fos.getChannel();
//② 分配一个指定大小的缓区域
ByteBuffer buf=ByteBuffer.allocate(1024);
//③ 将通道中的数据写入缓冲区
while (inchannel.read(buf)!=-1){
buf.flip();//切换读取数据的模式
//④ 将缓冲区的数据写入通道
outchannel.write(buf);
buf.clear();//清空缓冲区
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(outchannel!=null) {
try {
outchannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(inchannel!=null) {
try {
inchannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fis!=null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos!=null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//利用直接缓冲区完成文件的复制(内存映射文件)
@Test
public void test2() {
FileChannel inchannel = null;
FileChannel outchannel = null;
try {
inchannel = FileChannel.open(Paths.get("背景图.jpg"), StandardOpenOption.READ);
outchannel = FileChannel.open(Paths.get("背景图78.jpg"),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE_NEW);
//内存映射文件
MappedByteBuffer inmap = inchannel.map(FileChannel.MapMode.READ_ONLY, 0, inchannel.size());
MappedByteBuffer outmap = outchannel.map(FileChannel.MapMode.READ_WRITE, 0, inchannel.size());
//直接对缓冲区进行数据的读写操作
byte[] dst=new byte[inmap.limit()];
ByteBuffer byteBuffer1 = inmap.get(dst);
ByteBuffer byteBuffer2 = outmap.get(dst);
} catch (IOException e) {
e.printStackTrace();
} finally {
if(inchannel!=null) {
try {
inchannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(outchannel!=null) {
try {
outchannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//通道之间的数据传输(直接缓冲区)
@Test
public void test3() throws IOException {
FileChannel inchannel = FileChannel.open(Paths.get("背景图.jpg"), StandardOpenOption.READ);
FileChannel outchannel = FileChannel.open(Paths.get("背景图3.jpg"), StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE_NEW);
inchannel.transferTo(0,inchannel.size(),outchannel);
inchannel.close();
outchannel.close();
}
//分散与聚集
@Test
public void test4() throws IOException {
RandomAccessFile raf1 = new RandomAccessFile("1.txt", "rw");
//1.获取通道
FileChannel channel1 = raf1.getChannel();
//2.分配指定大小的缓冲区
ByteBuffer buffer1=ByteBuffer.allocate(100);
ByteBuffer buffer2=ByteBuffer.allocate(1024);
//3.分散读取
ByteBuffer[] buffers={buffer1,buffer2};
channel1.read(buffers);
for (ByteBuffer bytebuffer: buffers
) {
bytebuffer.flip();
}
System.out.println(new String(buffers[0].array(), 0, buffers[0].limit()));
System.out.println(("-----------------"));
System.out.println(new String(buffers[1].array(), 0, buffers[1].limit()));
//4.聚集写入
RandomAccessFile raf2=new RandomAccessFile("3.txt","rw");
FileChannel channel2=raf2.getChannel();
channel2.write(buffers);
channel1.close();
channel2.close();
}
//字符集
@Test
public void test6() throws CharacterCodingException {
Charset gbk = Charset.forName("GBK");
//获取编码器
CharsetEncoder encoder = gbk.newEncoder();
//获取解码器
CharsetDecoder decoder = gbk.newDecoder();
CharBuffer charBuffer = CharBuffer.allocate(1024);
charBuffer.put("卢本伟牛逼");
charBuffer.flip();
//编码
ByteBuffer byteBuffer = encoder.encode(charBuffer);
for (int i = 0; i < 10; i++) {
System.out.println(byteBuffer.get());
}
//解码
byteBuffer.flip();
CharBuffer charBuffer1 = decoder.decode(byteBuffer);
System.out.println(charBuffer1.toString());
}
@Test
public void test5(){
Map< String, Charset > map = Charset.availableCharsets();
Set< Map.Entry< String, Charset > > set = map.entrySet();
set.stream().forEach(System.out::println);
}
}