java学习笔记:NIO(NEW I/O)

java学习笔记:NIO(NEW I/O)

(一)为了实现更高效的I/O

(二)是对块进行处理,而不是对一个一个字节处理,这样会更高效。

(三)这里的块就是各种缓冲区,先把数据写到缓冲区中,然后将缓冲区的数据一并写到文件中。

(四)缓冲区类

  • ByteBuffer
  • ShortBuffer
  • CharBuffer
  • IntBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer

(五)以ByteBuffer为例介绍其中的一些方法和属性

  1. 首先ByteBuffer类提供了一个静态方法来分配缓存的大小,
  2. ByteBuffer b = ByteBuffer.allocate(8);
  3. ByteBuffer对象中有三个重要的属性,position,limit,capacity,position表示将要把数据插入到哪个位置,随着插入完一个数据后自动加一,limit表示访问缓存中的数据的最大小标,比如limit=8,那么就只能访问到这里,capacity表示缓存大小,limit的初始值和capacity相等。
  4. put方法将数据放到缓存中,有多种写法。
  5. get从缓存中得到数据,在使用get的时候,如果传入的下标超过了limit则会报错java.lang.IndexOutOfBoundsException
  6. flip方法会将limit=position,然后把position变成0。目的是将缓存中存有数据的部分标明出来,而访问没有数据的部分的时候就会报错java.lang.IndexOutOfBoundsException
  7. hasRemaining()方法会返回position和limit之间是否有数据
  8. remaining()会返回position和limit之间有多少个数据,内部实现是limit-position
  9. 对属性和方法进行检验
 //创建一个大小为8的缓存
  ByteBuffer b = ByteBuffer.allocate(8);
  //输出一下position,limit,capacity属性
  System.out.println("position="+b.position());
  System.out.println("limit="+b.limit());
  System.out.println("capacity="+b.capacity());
  //添加数据10,20,30
  b.put((byte)10);
  b.put((byte)20);
  b.put((byte)30);
  
  System.out.println("-----------------");
  //再输出一下position,limit,capacity。
  //发现position已经变成3了说明,下一个插入的数据要放在3这个位置上
  System.out.println("position="+b.position());
  System.out.println("limit="+b.limit());
  System.out.println("capacity="+b.capacity());
  
  //flip一下
  b.flip();
  //发现limit变成了3,position变成了0 这个时候说明0到2有数据
  System.out.println("-----------------");
  System.out.println("position="+b.position());
  System.out.println("limit="+b.limit());
  System.out.println("capacity="+b.capacity());
  //检测是否有数据
  if(b.hasRemaining()) {
   //得到数据数,然后用for循环遍历数据
   for(int i = 0 ;i<b.remaining() ; i++) {
    System.out.println(b.get(i));
    
   }
  }


(六)通道类Channel,在通道里传输的是块(也就是缓存),用户把数据存到缓存中,然后缓存经过管道存到文件中,或者管道将文件读取到缓存中,用户从缓存中得到字节。
(七)可以通过FileInputStream的getChannel方法返回一个FileChannel对象,从管道读取的时候需要一个缓存,然后再把东西写道管道中。类死于流,但是管道的write方法只会把缓存的positon到limit之间的数据写到管道里,所以在写入管道前调用一下flip方法(如果没有读取满就用flip来调整缓存中的limit),读取完写入到管道中,然后清空一下缓存以便下一次读取。

//如果直接用new FileInputStreamy("D:\\test\\test1.txt").getChannel这种写法
  //虽然返回了一个管道但会打开一个流,而这个流有没有名字,也就无法关闭。
  //所以分开写
  InputStream is = new  FileInputStream("D:\\test\\test1.txt");
  FileChannel fcIn = ((FileInputStream) is).getChannel();
  OutputStream os = new FileOutputStream("D:\\test\\test3.txt");
  FileChannel fcOut = ((FileOutputStream) os).getChannel();
  ByteBuffer buf = ByteBuffer.allocate(1024);
  while(fcIn.read(buf)!=-1) {
   buf.flip();
   //这里write方法只会读取ByteBuffer对象中position到limit之间的数据
    fcOut.write(buf);
   //清空一下缓存
   buf.clear();
  }
  is.close();
  os.close();
  fcIn.close();
  fcOut.close();

(八)RandomAccessFile中的内存映射,以输入管道创建一个映射缓存,这个映射缓存
在这里插入图片描述

RandomAccessFile read = new RandomAccessFile("D:\\test\\test1", "r");
  RandomAccessFile write = new RandomAccessFile("D:\\test\\test3", "rw");
  //获得输入输出管道
  FileChannel fcIn = read.getChannel();
  FileChannel fcOut = write.getChannel();
  //得到输入管道的长度
  long size = fcIn.size(); 
  //创建输入映射缓存,从0到size即把整个输入管道都映射到缓存中。
  //文件中所有的东西都会映射到缓存中。
  MappedByteBuffer inBuf = fcIn.map(MapMode.READ_ONLY, 0, size);
  //创建输出映射缓存,从0到size
  //所有映射缓存中的东西都会映射到文件中
  MappedByteBuffer outBuf = fcOut.map(MapMode.READ_ONLY, 0, size);
  //然后把输入映射缓存的东西全部写道输出映射缓存中,
  for(int i=0;i<size;i++) {
   outBuf.put(inBuf.get());
  }
  read.close();
  write.close();
  fcIn.close();
  fcOut.close();

(九)效率

  1. 映射
  2. 管道
  3. 带缓存的I/O
  4. 普通I/O
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值