学习记录-----NIO(一)

来源:互联网 发布:苏州盛科网络 被收购 编辑:程序博客网 时间:2024/06/06 06:50


--------------------------------------

    初识NIO.

     最近看了nio的知识。(new io 或者 non-blocking IO

     百度上的解释:java.nio全称java non-blocking IO,是指jdk1.4 及以上版本里提供的新api(New IO) ,为所有的原始类型(boolean类型除外)提供缓存支持的数据容器,使用它可以提供非阻塞式的高伸缩性网络

     主要的知识点:通道channel,缓存器(buffer),选择器(selector)

----------------------------------------------

     与io的区别



总结: IO像是水管流水,水流就是数据流。  Nio更像是铁轨火车。 buff像火车,通道像铁轨,数据先上火车,然后在通道上运输。

--------------------------------------------------------------

通道与缓冲区

 







----------------------------------------练习-------------------------------------------

一下两个练习主要针对 buffer的常用属性,已经channel 和buffer本地传输数据练习。


1.-------------------BufferTest.java--------------


package com.fjf.test;


import java.nio.ByteBuffer;


import org.junit.Test;




public class BufferTest {

//非直接缓存区
@Test
public void test01(){

System.out.println("---------------初始化buffer------");
ByteBuffer bf = ByteBuffer.allocate(1024);
System.out.println(bf.capacity());
System.out.println(bf.limit());
System.out.println(bf.position());


System.out.println("---------------put()------");
String str ="fujianfeng";
bf.put(str.getBytes());
System.out.println(bf.capacity());
System.out.println(bf.limit());
System.out.println(bf.position());


System.out.println("---------------flip()------");
bf.flip();
System.out.println(bf.capacity());
System.out.println(bf.limit());
System.out.println(bf.position());

System.out.println("---------------mark()------");
bf.mark();  //打个标记
System.out.println(bf.capacity());
System.out.println(bf.limit());
System.out.println(bf.position());

System.out.println("---------------get()------");
byte[] s = new byte[bf.limit()];
ByteBuffer bf2 = bf.get(s);
System.out.println(new String(s,0,s.length));
System.out.println(bf.capacity());
System.out.println(bf.limit());
System.out.println(bf.position());

System.out.println("---------------reset()------");
bf.reset();  //
System.out.println(bf.capacity());
System.out.println(bf.limit());
System.out.println(bf.position());

System.out.println("---------------clear()------");
bf.clear();  //
System.out.println(bf.capacity());
System.out.println(bf.limit());
System.out.println(bf.position());
}


//直接缓存区
@Test
public void test2(){
ByteBuffer bf = ByteBuffer.allocateDirect(512);
System.out.println(bf.isDirect());
}

}

2.----ChannelTest .java---

package com.fjf.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 java.util.RandomAccess;


import org.junit.Test;


/**
 * 学习nio通道的一些测试
 * @author fjf
 * 2017年11月23日 13:39:50
 */
public class ChannelTest {





//一.利用通道和buff 传文件(获取通道(通过含有FileChnnel的类,getchannel()))
@Test
public void test1(){

//1.获取通道(通过含有FileChnnel的类,getchannel())
FileInputStream fis = null;
FileOutputStream fos =null;
FileChannel inchannel =null;
FileChannel outchannel = null;
try {
fis = new FileInputStream("1.jpg");
fos = new FileOutputStream("2.jpg");
inchannel = fis.getChannel();
outchannel = fos.getChannel();

//2.通道的数据装到 buff上。运送,再用buff写入通道。 类似坐火车,人们上车,运输,人们下车
ByteBuffer buff = ByteBuffer.allocate(1024);
while(inchannel.read(buff)!=-1){
buff.flip();
outchannel.write(buff);
buff.clear();
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("通道传输有异常");
}finally{

//3.关闭  
try {
outchannel.close();
inchannel.close();
fis.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("关闭通道或流 有异常");
}
}
}

//二  利用通道和buff 传文件(获取channel(通过静态的open方法))  
@Test
public void test2() throws IOException{
//1.获取channel(通过静态的open方法)
FileChannel inChnnanel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
FileChannel outChnnanel = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.WRITE,StandardOpenOption.CREATE);

//2.
ByteBuffer buff = ByteBuffer.allocate(1024);
while(inChnnanel.read(buff)!=-1){
buff.flip();
outChnnanel.write(buff);
buff.clear();
}

inChnnanel.close();
outChnnanel.close();
}

//三  直接内存地址映射文件(直接缓存)
@Test
public void test3() throws IOException{
//1.获取channel(通过静态的open方法)
FileChannel inChnnanel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
FileChannel outChnnanel = FileChannel.open(Paths.get("4.jpg"), StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE);

//.内存映射文件
MappedByteBuffer inmapbytebuff = inChnnanel.map(MapMode.READ_ONLY, 0, inChnnanel.size());
MappedByteBuffer outmapbytebuff = outChnnanel.map(MapMode.READ_WRITE, 0, inChnnanel.size());

//.对缓存区进行读写
byte[] dst = new byte[inmapbytebuff.limit()];
inmapbytebuff.get(dst);
outmapbytebuff.put(dst);



inChnnanel.close();
outChnnanel.close();
}

//四  直接管道传输(直接缓存)
@Test
public void test4() throws IOException{
//1.获取channel(通过静态的open方法)
FileChannel inChnnanel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
FileChannel outChnnanel = FileChannel.open(Paths.get("d:/2.jpg"), StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE);

//直接管道传输
inChnnanel.transferTo(0, inChnnanel.size(), outChnnanel);


inChnnanel.close();
outChnnanel.close();
}
//五,分散读取,聚集写入
@Test
public void test5() throws IOException{
//1.获取通道

FileChannel readChnanel = FileChannel.open(Paths.get("1.txt"), StandardOpenOption.WRITE,StandardOpenOption.READ);
//RandomAccessFile raf1 = new RandomAccessFile("1.txt", "rw");    //用RandomAccessFile 获取channel
//FileChannel readChnanel = raf1.getChannel();

//多个buff,分散读取
ByteBuffer buf1 = ByteBuffer.allocate(100);
ByteBuffer buf2 = ByteBuffer.allocate(1024);
ByteBuffer[] bufarr = {buf1,buf2};
readChnanel.read(bufarr);

//遍历反转
for (ByteBuffer byteBuffer : bufarr) {
byteBuffer.flip();
System.out.println(new String(byteBuffer.array(),0,byteBuffer.limit()));
System.out.println("----------------");
}

//.获取通道,聚集写入
RandomAccessFile raf2 = new RandomAccessFile("2.txt", "rw");
FileChannel writeChnanel = raf2.getChannel();
writeChnanel.write(bufarr);
}
}

--------------------------------------

总结:


  一、缓冲区(Buffer):在 Java NIO 中负责数据的存取。缓冲区就是数组。用于存储不同数据类型的数据
  
  根据数据类型不同(boolean 除外),提供了相应类型的缓冲区:
  ByteBuffer
  CharBuffer
  ShortBuffer
  IntBuffer
  LongBuffer
  FloatBuffer
  DoubleBuffer
  
  上述缓冲区的管理方式几乎一致,通过 allocate() 获取缓冲区
  
  二、缓冲区存取数据的两个核心方法:
  put() : 存入数据到缓冲区中
  get() : 获取缓冲区中的数据
  
  三、缓冲区中的四个核心属性:
  capacity : 容量,表示缓冲区中最大存储数据的容量。一旦声明不能改变。
  limit : 界限,表示缓冲区中可以操作数据的大小。(limit 后数据不能进行读写)
  position : 位置,表示缓冲区中正在操作数据的位置。
  
  mark : 标记,表示记录当前 position 的位置。可以通过 reset() 恢复到 mark 的位置
  
  0 <= mark <= position <= limit <= capacity
  
  四、直接缓冲区与非直接缓冲区:
  非直接缓冲区:通过 allocate() 方法分配缓冲区,将缓冲区建立在 JVM 的内存中
  直接缓冲区:通过 allocateDirect() 方法分配直接缓冲区,将缓冲区建立在物理内存中。可以提高效率
 


  一、通道(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()
  3. 在 JDK 1.7 中的 NIO.2 的 Files 工具类的 newByteChannel()
  
  四、通道之间的数据传输
 transferFrom()
  transferTo()
  
  五、分散(Scatter)与聚集(Gather)
  分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区中
  聚集写入(Gathering Writes):将多个缓冲区中的数据聚集到通道中
  
-------------

学习资料上看的网络上尚硅谷视频,感谢。


原创粉丝点击