Java NIO中的通道(channel)介绍、通道的实现方式、直接缓冲区和非直接缓冲区、nio中的分散聚集。
/**
*
*
* 一.通道(channel):用于源节点和目标节点的连接。在Java nio中负责数据的传输,
* channel本身不存储数据,因此需要配合缓冲区进行传输。
*
* 写数据到Buffer有两种方式:
从Channel写到Buffer。 int bytesRead = inChannel.read(buf); //read into buffer.
通过Buffer的put()方法写到Buffer里。 buf.put(127);
从Buffer中读取数据有两种方式:
从Buffer读取数据到Channel。 int bytesWritten = inChannel.write(buf);
使用get()方法从Buffer中读取数据。 byte aByte = buf.get();
* 二.通道的主要实现类:
* java.nio.channels.Channel接口:
* |--FileChanel 文件通道,本地通道
* |--SocketChannel 网路io
* |--ServerSocketChannel 网路io
* |--DatagramChannel UDP 网路io
*
* 三.获取通道 三种方式
* 1.Java针对支持通道的类提供了getChannel()方法,获取对应的通道
* 本地IO:
* FileInputStream/FileOutputStream
* RandomAccessFile
*
* 网路IO
* Socket
* ServerSocket
* DatagramSocket
*
* 2.jdk1.7中的在NIO2中针对各个通道提供了静态方法open()
* 3.jdk1.7中的NIO2中的Files 工具类的newByteChannel()
*
* 四、通道之间的数据传输
* transferFrom()
* transferTo()
*
* 五、分散和聚集
* 分散读取:将通道中的数据分散到多个缓冲区
* 聚集写入:将多个缓冲区中的数据聚集到通道中
*
* 六、字符集Charset
* 编码:字符串转成字节数组
* 解码:字节数组转成字符串
*/
public class ChannelTest {
/**
* 1利用通道完成文件的复制
* 非直接缓冲区
* @throws IOException
*/
@Test
public void copy1() throws IOException {
long start = System.currentTimeMillis();
//2.获取通道
FileChannel inChannel= null;
FileChannel outChannel= null;
// FileInputStream fis = new FileInputStream("1.jpg");
// FileOutputStream fos = new FileOutputStream("2.jpg");
FileInputStream fis = new FileInputStream("d:/1.rar");
FileOutputStream fos = new FileOutputStream("d:/2.rar");
inChannel = fis.getChannel();
outChannel = fos.getChannel();
//3分配指定大小的缓冲区
ByteBuffer buf = ByteBuffer.allocate(1024);
//4将通道中的数据存入缓冲区
while (inChannel.read(buf) != -1) {
buf.flip(); //切换成读取数据的模式
//将缓冲区中的数据写入通道中
outChannel.write(buf);
buf.clear();//清空缓冲区
}
System.out.println("耗时:"+(System.currentTimeMillis() - start));
}
/**
* 使用直接缓冲区 完成文件的复制(内存映射文件(直接缓冲区))
*/
@Test
public void copy2() {
long start = System.currentTimeMillis();
try {
//Paths.get("d:/","a/")可变参数,可以拼接地址
// FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"),StandardOpenOption.READ);
// FileChannel outChannel = FileChannel.open(Paths.get("3.jpg"),StandardOpenOption.READ,
// StandardOpenOption.WRITE,StandardOpenOption.CREATE_NEW);//CREATE 创建,如果有就覆盖 CREATE_NEW 创建,如果有就报错
FileChannel inChannel = FileChannel.open(Paths.get("d:/","1.rar"),StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("d:/","2.rar"),StandardOpenOption.READ,
StandardOpenOption.WRITE,StandardOpenOption.CREATE);//CREATE 创建,如果有就覆盖 CREATE_NEW 创建,如果有就报错
//内存映射文件(直接缓冲区)
//ByteBuffer.allocateDirect(capacity)
MappedByteBuffer inMapBuffer = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outMapBuffer = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
//直接对缓冲区进行数据的读写操作
byte[] dst = new byte[inMapBuffer.limit()];
inMapBuffer.get(dst);
outMapBuffer.put(dst);
inChannel.close();
outChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("耗时:"+(System.currentTimeMillis() - start));
}
/**
* 通道之间的数据传输
* transferTo() transferFrom()
*/
@Test
public void copy3() {
long start = System.currentTimeMillis();
try {
FileChannel inChannel = FileChannel.open(Paths.get("d:/1.rar"),StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("d:/2.rar"),StandardOpenOption.READ,
StandardOpenOption.WRITE,StandardOpenOption.CREATE_NEW);//CREATE 创建,如果有就覆盖 CREATE_NEW 创建,如果有就报错
inChannel.transferTo(0, inChannel.size(), outChannel);
// outChannel.transferFrom(inChannel, 0, inChannel.size());
outChannel.close();
inChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("耗时:"+(System.currentTimeMillis() - start));
}
/**
* 分散与聚集
*/
@Test
public void scatterGather() {
try {
RandomAccessFile raf = new RandomAccessFile("1.txt", "rw");//读写模式
//获取通道
FileChannel channel1 = raf.getChannel();
//分配指定大小的缓冲区
ByteBuffer buf1 = ByteBuffer.allocate(100);
ByteBuffer buf2 = ByteBuffer.allocate(1024);
//分散读取
ByteBuffer[] dsts = {buf1,buf2};
channel1.read(dsts);
for (ByteBuffer byteBuffer : dsts) {
byteBuffer.flip();
}
System.out.println(new String(dsts[0].array(), 0, dsts[0].limit()));
System.out.println("--------------------------------------------");
System.out.println(new String(dsts[1].array(), 0, dsts[1].limit()));
//聚集写入
RandomAccessFile raf1 = new RandomAccessFile("2.txt", "rw");
FileChannel channel2 = raf1.getChannel();
channel2.write(dsts);
channel2.close();
channel1.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取所有字符集
* 2018年7月24日
*/
@Test
public void getCharset(){
SortedMap<String, Charset> map = Charset.availableCharsets();
for (Map.Entry<String, Charset> entry : map.entrySet()) {
System.out.println(entry.getKey()+"=="+entry.getValue());
}
}
/**
* 编码解码
*/
@Test
public void encoderDecode(){
try {
Charset charset = Charset.forName("GBK");
//获取编码器
CharsetEncoder newEncoder = charset.newEncoder();
//获取解码器
CharsetDecoder newDecoder = charset.newDecoder();
CharBuffer charBuffer = CharBuffer.allocate(1024);
charBuffer.put("你好!");
charBuffer.flip();
//编码
ByteBuffer byteBuffer = newEncoder.encode(charBuffer);
for (int i = 0; i <10; i++) {
System.out.println(byteBuffer.get());
}
byteBuffer.flip();
//解码
CharBuffer charBuffer2 = newDecoder.decode(byteBuffer);
System.out.println(charBuffer2.toString());
} catch (CharacterCodingException e) {
e.printStackTrace();
}
}
}