java的nio入门基础
Posted 白日梦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java的nio入门基础相关的知识,希望对你有一定的参考价值。
1.nio的简介
nio的FileChannel类可以获取的方法有 FileInputStream和FileOutputStream以及RandomAccessFile的getChannel方法,或者FileChannel类的open方法等获取,SocketChannel,ServerSocketChannel,DatagramChannel,同样可以Socket,ServerSocket的getChannel方法和open方法(tcp)等获取,DatagramChannel可以通过open方法获取(udf)等方法获取,Pipe也可以同过open等方法获取,他们只是建立通道,并不参与数据的输入和输出,输入和输出是buffer完成的,buffer有直接缓存区和非直接缓存区两种,直接缓存建立在物理内存上的,建立和销毁allocateDirect的空间的开销比较大,传递的效率要比非直接缓冲区要好(因为直接缓存区只需要复制一次,而非直接缓存区需要复制两次,直接缓存区较非直接缓存区减少了一次复制),所以通常用于传递allocateDirect的空间开创的比较大的时候,用利于传输比较大的文件,但是太大例如超过几个G,那么可以通过分段的方式来传输,非直接缓存区是建立在堆上的,受到jvm的限制。
2.Buffer
常用的方法有position limit capacity mark reset rewind hasRemaining remaining flip clear isDirect等以及get,put方法(position会相应的移动)但是又较多的重载方法,没有参数的表示返回游标位置的数据或者放入数据,数组表示向数组中放入数据或者向数组中写入数据。
public class ByteBufferTest { public static void main(String[] args) { ByteBuffer buffer = ByteBuffer.allocate(10); if (!buffer.isDirect()) { System.out.println("非直接缓冲区");// 非直接缓冲区 } System.out.println(buffer.position());// 位置0 System.out.println(buffer.limit());// 界限10 System.out.println(buffer.capacity());// 开辟的空间10 buffer.put((byte) ‘a‘); System.out.println("-------------"); System.out.println(buffer.position());// 位置1 System.out.println(buffer.limit());// 界限10 System.out.println(buffer.capacity());// 开辟的空间10 byte[] bys = { (byte) ‘b‘, (byte) ‘c‘ }; buffer.put(bys); buffer.mark(); System.out.println("-------------"); System.out.println(buffer.position());// 位置3 System.out.println(buffer.limit());// 界限10 System.out.println(buffer.capacity());// 开辟的空间10 buffer.reset(); System.out.println("-------------"); System.out.println(buffer.position());// 位置1 System.out.println(buffer.limit());// 界限10 System.out.println(buffer.capacity());// 开辟的空间10 buffer.flip();// 将limit设置为当前位置,position设置为0 System.out.println("-------------"); System.out.println(buffer.position());// 位置0 System.out.println(buffer.limit());// 界限1 System.out.println(buffer.capacity());// 开辟的空间10 buffer.rewind();// limit不变,position变为0,且去除mark buffer.flip(); System.out.println("-------------"); System.out.println(buffer.position());// 位置0 System.out.println(buffer.limit());// 界限0 System.out.println(buffer.capacity());// 开辟的空间10 try { buffer.reset(); System.out.println("-------------"); System.out.println(buffer.position()); System.out.println(buffer.limit()); System.out.println(buffer.capacity()); } catch (Exception e) { System.out.println("mark标记不存在了"); } buffer.limit(3); buffer.position(3);//position<=limit<=capacity buffer.flip(); System.out.println(buffer.remaining());//position与limit之间还剩多少元素3 System.out.println("-------------"); System.out.println(buffer.position());// 位置0 System.out.println(buffer.limit());// 界限3 System.out.println(buffer.capacity());// 开辟的空间10 while(buffer.hasRemaining()){//position和limit之间是否还有元素 System.out.println((char)buffer.get());// a b c } System.out.println("------------"); System.out.println(buffer.position());// 位置3 System.out.println(buffer.limit());// 界限3 System.out.println(buffer.capacity());// 开辟的空间10 byte[] bys1 = { (byte) ‘d‘, (byte) ‘e‘, (byte) ‘f‘}; buffer.limit(9); buffer.put(bys1); buffer.position(7); /*limit变为等于capacity,position的位置等于limit-position,在limit-position的 数据相应的往前移覆盖position开始的同样多的数据*/ buffer.compact(); System.out.println("------------"); System.out.println(buffer.position());// 位置2 System.out.println(buffer.limit());// 界限10 System.out.println(buffer.capacity());// 开辟的空间10 while(buffer.hasRemaining()){//position和limit之间是否还有元素 System.out.println((char)buffer.get());// c d e f 4个空格 } } }
其他的buffer类似
3.FileChannel
public class FileChannelTest { public static void main(String[] args) throws IOException { // 非直接缓冲区 // 方式1 FileChannel channel1 = null; FileChannel channel2 = null; try { channel1 = new FileInputStream("1.txt").getChannel(); channel2 = new FileOutputStream("3.txt").getChannel(); ByteBuffer allocate = ByteBuffer.allocate(1024); while (channel1.read(allocate) != -1) { allocate.flip(); channel2.write(allocate); allocate.clear(); } } finally { channel1.close(); channel2.close(); } // 方式2 FileChannel channel3 = new RandomAccessFile("1.txt", "r").getChannel(); FileChannel channel4 = new RandomAccessFile("4.txt", "rw").getChannel(); ByteBuffer allocate1 = ByteBuffer.allocate(1024); while (channel3.read(allocate1) != -1) { allocate1.flip(); channel4.write(allocate1); allocate1.clear(); } channel3.close(); channel4.close(); // 方式3 FileChannel open1 = FileChannel.open(Paths.get("1.txt"), StandardOpenOption.READ); // StandardOpenOption.CREATE // 有就覆盖,没有就创建,StandardOpenOption.CREATE_NEW有就报错,没有就创建 FileChannel open2 = FileChannel.open(Paths.get("5.txt"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW); ByteBuffer allocate2 = ByteBuffer.allocate(1024); while (open1.read(allocate2) != -1) { allocate2.flip(); open2.write(allocate2); allocate2.clear(); } open1.close(); open2.close(); // 直接缓冲区 // 方式1 FileChannel channel5 = null; FileChannel channel6 = null; try { channel5 = new FileInputStream("1.txt").getChannel(); channel6 = new FileOutputStream("6.txt").getChannel(); MappedByteBuffer map = channel5.map(MapMode.READ_ONLY, 0, channel5.size()); channel6.write(map); } finally { channel5.close(); channel6.close(); } // 方式2 FileChannel open3 = FileChannel.open(Paths.get("1.txt"), StandardOpenOption.READ); // StandardOpenOption.CREATE有就覆盖,没有就创建,StandardOpenOption.CREATE_NEW有就报错,没有就创建 FileChannel open4 = FileChannel.open(Paths.get("7.txt"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW); ByteBuffer allocate3 = ByteBuffer.allocateDirect(1024); while (open3.read(allocate3) != -1) { allocate3.flip(); open4.write(allocate3); allocate3.clear(); } open3.close(); open4.close(); // 方式3 FileChannel open5 = FileChannel.open(Paths.get("1.txt"), StandardOpenOption.READ); // StandardOpenOption.CREATE // 有就覆盖,没有就创建,StandardOpenOption.CREATE_NEW有就报错,没有就创建 FileChannel open6 = FileChannel.open(Paths.get("8.txt"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW); MappedByteBuffer map1 = open5.map(MapMode.READ_ONLY, 0, open4.size()); MappedByteBuffer map2 = open6.map(MapMode.READ_WRITE, 0, open4.size()); // open4.size()不能太大否则会超出int的范围 byte[] dst1 = new byte[(int) open4.size()]; // 将数据放入dst1中 map1.get(dst1); // 将dst1写入文件中 map2.put(dst1); open5.close(); open6.close(); // 方式4 FileChannel open7 = FileChannel.open(Paths.get("1.txt"), StandardOpenOption.READ); // StandardOpenOption.CREATE // 有就覆盖,没有就创建,StandardOpenOption.CREATE_NEW有就报错,没有就创建 FileChannel open8 = FileChannel.open(Paths.get("9.txt"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW); open7.transferTo(0, open7.size(), open8); // open8.transferTo(position, count, target) open7.close(); open8.close(); } }
4.直接缓存区域与非直接缓冲区的效率比较
public static void main(String[] args) throws IOException { long start=System.currentTimeMillis(); String filePath="F:/test/1.wmv"; FileChannel inch1 = new FileInputStream(filePath).getChannel(); FileChannel outch1 = new FileOutputStream("2.wmv").getChannel(); ByteBuffer bf1 = ByteBuffer.allocate(2); while(inch1.read(bf1)!=-1){ bf1.flip(); outch1.write(bf1); bf1.clear(); } inch1.close(); outch1.close(); long end=System.currentTimeMillis(); System.out.println(end-start);//189388
//当allocate为4的时候,时间为100988 System.gc(); System.runFinalization(); start=System.currentTimeMillis(); FileChannel inch2 = new FileInputStream(filePath).getChannel(); FileChannel outch2 = new FileOutputStream("3.wmv").getChannel(); ByteBuffer bf2 = ByteBuffer.allocateDirect(2); while(inch2.read(bf2)!=-1){ bf2.flip(); outch2.write(bf2); bf2.clear(); } inch2.close(); outch2.close(); end=System.currentTimeMillis(); System.out.println(end-start);//190209 } }
public static void main(String[] args) throws IOException { long start=System.currentTimeMillis(); String filePath="F:/test/1.wmv"; FileChannel inch1 = new FileInputStream(filePath).getChannel(); FileChannel outch1 = new FileOutputStream("2.wmv").getChannel(); ByteBuffer bf1 = ByteBuffer.allocate(10000); while(inch1.read(bf1)!=-1){ bf1.flip(); outch1.write(bf1); bf1.clear(); } inch1.close(); outch1.close(); long end=System.currentTimeMillis(); System.out.println(end-start);//200 System.gc(); System.runFinalization(); start=System.currentTimeMillis(); FileChannel inch2 = new FileInputStream(filePath).getChannel(); FileChannel outch2 = new FileOutputStream("3.wmv").getChannel(); ByteBuffer bf2 = ByteBuffer.allocateDirect(10000); while(inch2.read(bf2)!=-1){ bf2.flip(); outch2.write(bf2); bf2.clear(); } inch2.close(); outch2.close(); end=System.currentTimeMillis(); System.out.println(end-start);//90 System.gc(); System.runFinalization(); start=System.currentTimeMillis(); FileChannel inch3 = new FileInputStream(filePath).getChannel(); FileChannel outch3 = new FileOutputStream("4.wmv").getChannel(); inch3.transferTo(0, inch3.size(), outch3); inch3.close(); outch3.close(); end=System.currentTimeMillis(); System.out.println(end-start);//33 } }
5.SocketChannel
待续
以上是关于java的nio入门基础的主要内容,如果未能解决你的问题,请参考以下文章