Java IO流和NIO流读写文件比较
2015-10-31 16:52
169 查看
Java IO流和NIO流读写文件比较
本文主要讨论Java中使用流读写文件的两种方式:IO读写和NIO读写。最近看到一些关于NIO 新的IO流的知识,抱着好奇的心态去比较了两个。本文主要是比较使用两种不同的流操作去读取一个文件写入另外一个文件中,先写点关于NIO知识的基本概念吧,也好日后给自己复习使用。
使用NIO流读写文件:控制台输出打印为=========总共耗时:0ms,耗时基本上为0
NIO中主要的概念有Channel和Buffer这两个对象,可以通过Channel来读取和写入数据
,就跟io里面的流一样。在java nio中所有的操作都是通过buffer来进行的,也就是说您永远也不会将字节写入通道中。相反,是将数据写入包含一个或者多个字节的缓冲区,读取也一样。又因为通道是双向的,所以读写速度都很快。
从上面的例子可以看出,读跟写文件基本上需要3个步骤来进行。首选,从fileInputStream获取channel
,其次 创建buffer,最好从channel读取或者写入buffer中。
例子中的buffer.clear()跟buffer.flip()的用法
clear() 方法重设缓冲区,使它可以接受读入的数据。 flip() 方法让缓冲区可以将新读入的数据写入另一个通道。
可以用三个值指定缓冲区在任意时刻的状态:
• position
• limit
• capacity
这三个变量一起可以跟踪缓冲区的状态和它所包含的数据。
Position
缓冲区实际上就是美化了的数组。在从通道读取时,您将所读取的数据放到底层的数组中。 position 变量跟踪已经写了多少数据。更准确地说,它指定了下一个字节将放到数组的哪一个元素中。因此,如果您从通道中读三个字节到缓冲区中,那么缓冲区的 position 将会设置为3,指向数组中第四个元素。
同样,在写入通道时,您是从缓冲区中获取数据。 position 值跟踪从缓冲区中获取了多少数据。更准确地说,它指定下一个字节来自数组的哪一个元素。因此如果从缓冲区写了5个字节到通道中,那么缓冲区的 position 将被设置为5,指向数组的第六个元素。
Limit
limit 变量表明还有多少数据需要取出(在从缓冲区写入通道时),或者还有多少空间可以放入数据(在从通道读入缓冲区时)。
position 总是小于或者等于 limit。
Capacity
缓冲区的 capacity 表明可以储存在缓冲区中的最大数据容量。实际上,它指定了底层数组的大小 ― 或者至少是指定了准许我们使用的底层数组的容量。
limit 决不能大于 capacity。
而我们使用传统的IO流读写的时候:
没想到,这两种方式的效率方面会有这么大的差距,,,,,我想,应该就是NIO内部维护了一个更加效率高的Buffer缓冲数组对象。
本文主要讨论Java中使用流读写文件的两种方式:IO读写和NIO读写。最近看到一些关于NIO 新的IO流的知识,抱着好奇的心态去比较了两个。本文主要是比较使用两种不同的流操作去读取一个文件写入另外一个文件中,先写点关于NIO知识的基本概念吧,也好日后给自己复习使用。
//使用nio流读写文件 private static void useNioRWfile(String inFile, String outFile) throws FileNotFoundException, IOException { //获取源文件和目标文件的输入输出流 FileInputStream fin = new FileInputStream(inFile); FileOutputStream fos = new FileOutputStream(outFile); try{ //获取输入输出通道 FileChannel fcin = fin.getChannel(); FileChannel fcout = fos.getChannel(); //创建1024字节的缓存区 ByteBuffer buffer = ByteBuffer.allocate(1024); long start = System.currentTimeMillis(); while(true){ //重设此缓冲区,使它可以接受读入的数据。Buffer对象中的limit=capacity; buffer.clear(); //从输入通道中将数据读入到缓冲区 int temp = fcin.read(buffer); if(temp == -1){ break; } //让缓冲区将新入读的输入写入另外一个通道.Buffer对象中的limit=position buffer.flip(); //从输出通道中将数据写入缓冲区 fcout.write(buffer); } System.out.println("总共耗时:"+(System.currentTimeMillis()-start)+"ms"); } finally { if(fin!=null) fin.close(); if(fos != null) fos.close(); } }
使用NIO流读写文件:控制台输出打印为=========总共耗时:0ms,耗时基本上为0
NIO中主要的概念有Channel和Buffer这两个对象,可以通过Channel来读取和写入数据
,就跟io里面的流一样。在java nio中所有的操作都是通过buffer来进行的,也就是说您永远也不会将字节写入通道中。相反,是将数据写入包含一个或者多个字节的缓冲区,读取也一样。又因为通道是双向的,所以读写速度都很快。
从上面的例子可以看出,读跟写文件基本上需要3个步骤来进行。首选,从fileInputStream获取channel
,其次 创建buffer,最好从channel读取或者写入buffer中。
例子中的buffer.clear()跟buffer.flip()的用法
clear() 方法重设缓冲区,使它可以接受读入的数据。 flip() 方法让缓冲区可以将新读入的数据写入另一个通道。
可以用三个值指定缓冲区在任意时刻的状态:
• position
• limit
• capacity
这三个变量一起可以跟踪缓冲区的状态和它所包含的数据。
Position
缓冲区实际上就是美化了的数组。在从通道读取时,您将所读取的数据放到底层的数组中。 position 变量跟踪已经写了多少数据。更准确地说,它指定了下一个字节将放到数组的哪一个元素中。因此,如果您从通道中读三个字节到缓冲区中,那么缓冲区的 position 将会设置为3,指向数组中第四个元素。
同样,在写入通道时,您是从缓冲区中获取数据。 position 值跟踪从缓冲区中获取了多少数据。更准确地说,它指定下一个字节来自数组的哪一个元素。因此如果从缓冲区写了5个字节到通道中,那么缓冲区的 position 将被设置为5,指向数组的第六个元素。
Limit
limit 变量表明还有多少数据需要取出(在从缓冲区写入通道时),或者还有多少空间可以放入数据(在从通道读入缓冲区时)。
position 总是小于或者等于 limit。
Capacity
缓冲区的 capacity 表明可以储存在缓冲区中的最大数据容量。实际上,它指定了底层数组的大小 ― 或者至少是指定了准许我们使用的底层数组的容量。
limit 决不能大于 capacity。
而我们使用传统的IO流读写的时候:
//使用普通的io流读写文件 private static void useIoRWfile(String inFile, String outFile) throws FileNotFoundException, IOException { //获取源文件和目标文件的输入输出流 FileInputStream fin = new FileInputStream(inFile); BufferedInputStream bis=new BufferedInputStream(fin); //连接带缓冲的输入流 FileOutputStream fos = new FileOutputStream(outFile); BufferedOutputStream bos=new BufferedOutputStream(fos); //连接带缓冲的输出流 try{ int temp = 0; long start = System.currentTimeMillis(); while((temp=fin.read())!=-1){ bos.write(temp); //写数据 bos.flush(); //强制输出 } System.out.println("总共耗时:"+(System.currentTimeMillis()-start)+"ms"); } finally { if(fin!=null) fin.close(); if(fos != null) fos.close(); if(bis!=null) bis.close(); if(bos!=null) bos.close(); } }控制台打印输出为:===========总共耗时:406ms
没想到,这两种方式的效率方面会有这么大的差距,,,,,我想,应该就是NIO内部维护了一个更加效率高的Buffer缓冲数组对象。
相关文章推荐
- Java基础学习16(super关键字)
- JAVA的堆排序
- java中点画线法——画椭圆
- Spring学习笔记(一)
- 编码规范系列(一):Eclipse Code Templates设置
- Java线程死锁查看分析方法
- 设置自己Eclipse代码风格(内部)
- SpringMVC 文件上传下载
- java连接mysql查询操作
- Java内部类总结 (吐血之作)
- Java学习笔记之内部类和匿名类
- java中的内部类总结
- 登录和注册(struts2+hibernate+spring)
- java泛型笔记
- JAVA的归并排序
- Java如何发送Email/邮件
- Java入门(1)
- Java注解
- Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)
- Eclipse搭建SSH(Struts2+Spring3+Hibernate3)框架项目教程