一、通道(Channel):用于源节点与目标节点的连接。在 Java NIO 中负责缓冲区中数据的传输。Channel 本身不存储数据,因此需要配合缓冲区进行传输。
二、通道的主要实现类
java.nio.channels.Channel 接口:
|--FileChannel
|--SocketChannel
|--ServerSocketChannel
|--DatagramChannel
三、获取通道
1. Java 针对支持通道的类提供了 getChannel() 方法
本地 IO:
FileInputStream/FileOutputStream
RandomAccessFile
网络IO:
Socket
ServerSocket
DatagramSocket
2. 在 JDK 1.7 中的 NIO.2 针对各个通道提供了静态方法 open()
二、通道的主要实现类
java.nio.channels.Channel 接口:
|--FileChannel
|--SocketChannel
|--ServerSocketChannel
|--DatagramChannel
三、获取通道
1. Java 针对支持通道的类提供了 getChannel() 方法
本地 IO:
FileInputStream/FileOutputStream
RandomAccessFile
网络IO:
Socket
ServerSocket
DatagramSocket
2. 在 JDK 1.7 中的 NIO.2 针对各个通道提供了静态方法 open()
3. 在 JDK 1.7 中的 NIO.2 的 Files 工具类的 newByteChannel()
使用直接缓冲区可以提高效率,具体可参看另外一篇博客;csdn这个玩意写完代码怎么就不能写其他文字啊,搞的
我只能写上面.
package nio;
import org.junit.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.file.Paths;
import java.nio.file.StandardOpenOption;
/**
* Created by ZWZS on 2018/1/25.
*/
public class TestChannel {
@Test
//通道之间的数据传输(利用这个可以复制文件)
public void test2() {
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
//获取channle
inChannel = FileChannel.open(Paths.get("d:/BaiduNetdiskDownload/1_什么叫做数据结构.swf"), StandardOpenOption.READ);
outChannel = FileChannel.open(Paths.get("d:/BaiduNetdiskDownload/2.swf"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW);
//inChannel.transferTo(0, inChannel.size(), outChannel);
outChannel.transferFrom(inChannel,0,inChannel.size());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inChannel.close();
outChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
//使用直接内存映射文件来复制文件
public void test() {
FileChannel inChannel = null;
FileChannel outChannel = null;
long start = 0;
try {
start = System.currentTimeMillis();
//获取channle
inChannel = FileChannel.open(Paths.get("d:/BaiduNetdiskDownload/1_什么叫做数据结构.swf"), StandardOpenOption.READ);
//StandardOpenOption.READ必须要添加读,因为FileChannel.MapMode.READ_WRITE只有读写,如果不添加读channel,会抛出无法读的异常
outChannel = FileChannel.open(Paths.get("d:/BaiduNetdiskDownload/2.swf"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW);
//内存映射文件
MappedByteBuffer inBuffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outBuffer = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());
//直接对缓冲区进行读写
byte[] bytes = new byte[inBuffer.limit()];
inBuffer.get(bytes); //读
outBuffer.put(bytes); //写
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inChannel.close();
outChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("所用的时间是:" + (end - start));
}
@Test
//利用通道完成文件的复制(非直接缓冲区)
public void copyFile() {
long start = 0;
start=System.currentTimeMillis();
FileChannel inChannel = null;
FileChannel outChannel = null;
FileInputStream inputStream=null;
FileOutputStream outputStream=null;
try {
inputStream = new FileInputStream("d:/BaiduNetdiskDownload/1_什么叫做数据结构.swf");
outputStream = new FileOutputStream("d:/BaiduNetdiskDownload/2.swf");
//获取通道
inChannel = inputStream.getChannel();
outChannel = outputStream.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (inChannel.read(buffer) != -1) {
//解释下inChannel.read(buffer),类似于java中IO流的read(),此前一直没有搞明白,
//单纯的read()只会每次读取一个字节,而使用字节数组,每次就读取的是对应的数组大小
//例如总共102字节,byte[] 为10,则 需要读11次,前10次每次10字节,第11次读2个字节
//读一个下次就自动到下一个,如果碰到-1说明没有值了.
buffer.flip();// 切换到读取模式
outChannel.write(buffer);
buffer.clear(); //清空buffer,继续往缓冲区读入数据
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inChannel.close();
outChannel.close();
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("所用的时间是:" + (end - start));
}
}