Java IO和NIO读取大文件,对比速度_javanio更适合处理大量小文件,而java lo更适合处理少量大文件-程序员宅基地

技术标签: 其他  File  

话题:假设机器只有500M内存,有一个1.23GB的文件,要从一个目录复制到另外一个目录
目的:比较IO与NIO的读取速度效率
细节:大文件不能一次读到内存中,否则会内存溢出,只能每次读取固定大小的数据流

在这里插入图片描述
下面进行代码实现,在实现代码中,有的代码是一次性读取全部内容到内存中,有的是读取固定大小,分别看看这些方法读取文件速度的差异

文件大小 1.23GB
1.使用RandomAccessFile读取文件,FileOutputStream写文件,耗时:8768ms
2.使用BufferedInputStream读取文件,BufferedOutputStream写文件,耗时:2202ms
3.使用Scanner读文件,FileOutputStream写文件,耗时:120945ms
4.使用NIO,FileChannel读写文件,耗时:

  • NIO每次读取1M,耗时:8947ms
  • NIO每次读取5M,耗时:2976ms
  • NIO每次读取10M,耗时:1802ms
  • NIO每次读取20M,耗时:1279ms

基本上使用NIO和有缓冲区的IO–BufferedInputStream读写文件速度最快,通过任务管理器观察对内存的使用基本在100M上下浮动
在这里插入图片描述

package com.zypcy.readbigfile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Scanner;

/**
 * 读取大文件
 * 分别测试不同文件流IO与NIO读取的效率
 * 因文件很大,机器可用内存较小,无法一次读取全部内容,需要读取固定大小的数据
 * @author zhuyu
 */
public class Demo {
    

	public static void main(String[] args) {
    
		String filePath = "D:\\project\\java\\workspace\\DemoThread\\src\\com\\zypcy\\readbigfile\\bigdata.zip";
		String newPath = "D:\\project\\java\\workspace\\DemoThread\\src\\com\\zypcy\\readbigfile\\output.zip";
		
		try {
    
			File file = new File(filePath);
			if(!file.exists()){
    
				return;
			}
			File newFile = new File(newPath);
			
			//randomAccessRead(file ,newFile); 
			//测试:读取1.23GB文件耗时:8768ms
			
			//bufferedRead(file ,newFile);
			//测试:读取1.23GB文件耗时:2202ms
			
			//scannerRead(file ,newFile);
			//测试:读取1.23GB文件耗时:120945ms
			
			fileChannelRead(file ,newFile);
			//每次读取1M,耗时:8947ms
			//每次读取5M,耗时:2976ms
			//每次读取10M,耗时:1802ms
			//每次读取20M,耗时:1279ms
		} catch (Exception e) {
    
			e.printStackTrace();
		}
	}
	
	/**
	 * 使用 RandomAccessFile 读取文件
	 * @param file
	 * @param newFile
	 */
	public static void randomAccessRead(File file , File newFile){
    
		//测试:读取1.23GB文件耗时:8768ms
		long d1 = System.currentTimeMillis();
		RandomAccessFile raf = null;
		OutputStream output = null;
		try {
    
			raf = new RandomAccessFile(file , "rw");
			output = new FileOutputStream(newFile);
			int len = 0;             //每次读取内容长度
			byte[] data = new byte[1024];//内容缓冲区
			while((len = raf.read(data)) != -1){
    
				output.write(data, 0, len);
			}
			long d2 = System.currentTimeMillis();
			System.out.println("randomAccessRead读取完成,耗时:" + (d2 - d1));
		} catch (Exception e) {
    
			e.printStackTrace();
		}finally{
    
			try {
    
				if(raf != null){
    
					raf.close();
				}
				if(output != null){
    
					output.close();
				}
			} catch (IOException e) {
    
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 使用NIO的FileChannel读取
	 * @param file
	 * @param newFile
	 */
	public static void fileChannelRead(File file , File newFile){
    
		//1.23GB文件
		//每次读取1M,耗时:8947ms
		//每次读取5M,耗时:2976ms
		//每次读取10M,耗时:1802ms
		//每次读取20M,耗时:1279ms
		long d1 = System.currentTimeMillis();
		FileInputStream in = null;
		FileOutputStream output = null;
		FileChannel  fic = null;
		FileChannel  foc = null;
		try {
    
			in = new FileInputStream(file);
			output = new FileOutputStream(newFile);
			fic = in.getChannel();
			foc = output.getChannel();
			
			//fic.transferTo(0, fic.size(), foc);
			ByteBuffer buf = ByteBuffer.allocate(20480);
			while(fic.read(buf) != -1){
    
				buf.flip();//切换到读取数据模式
				foc.write(buf);//将缓冲区的数据写入通道中
				buf.clear();//清空缓冲区
			}
			
			long d2 = System.currentTimeMillis();
			System.out.println("fileChannelRead读取完成,耗时:" + (d2 - d1));
		} catch (Exception e) {
    
			e.printStackTrace();
		}finally{
    
				try {
    
					if(in != null){
    
						in.close();
					}
					if(output != null){
    
						output.close();
					}
				} catch (IOException e) {
    
					e.printStackTrace();
				}
		}
	}
	
	/**
	 * 使用IO的缓冲区读取
	 * @param file
	 * @param newFile
	 */
	public static void bufferedRead(File file , File newFile){
    
		//测试:读取1.23GB文件耗时:2202
		long d1 = System.currentTimeMillis();
		InputStream in = null;
		OutputStream output = null;
		try {
    
			in = new BufferedInputStream(new FileInputStream(file)) ;
			output = new BufferedOutputStream(new FileOutputStream(newFile));
			int len = 0;
			byte[] data = new byte[1024];
			while((len = in.read(data)) != -1){
    
				output.write(data, 0, len);
			}
			long d2 = System.currentTimeMillis();
			System.out.println("bufferedRead读取完成,耗时:" + (d2 - d1));
		} catch (Exception e) {
    
			e.printStackTrace();
		}finally{
    
				try {
    
					if(in != null){
    
						in.close();
					}
					if(output != null){
    
						output.close();
					}
				} catch (IOException e) {
    
					e.printStackTrace();
				}
		}
	}
	
	/**
	 * 使用Scanner一行一行读取
	 * @param file
	 * @param newFile
	 */
	public static void scannerRead(File file , File newFile){
    
		//读取1.23GB文件耗时:120945
		long d1 = System.currentTimeMillis();
		InputStream in = null;
		OutputStream output = null;
		try {
    
			in = new FileInputStream(file);
			output = new FileOutputStream(newFile);
			Scanner sc = new Scanner(in, "UTF-8");
			//sc.useDelimiter("\\r\\n");
			while(sc.hasNext()){
    
				String content = sc.nextLine();
				output.write(content.getBytes("UTF-8"));
			}
			long d2 = System.currentTimeMillis();
			System.out.println("scannerRead读取完成,耗时:" + (d2 - d1));
		} catch (Exception e) {
    
			e.printStackTrace();
		}finally{
    
				try {
    
					if(in != null){
    
						in.close();
					}
					if(output != null){
    
						output.close();
					}
				} catch (IOException e) {
    
					e.printStackTrace();
				}
		}
	}
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhuyu19911016520/article/details/104411275

智能推荐

研究生如何读文献 写论文 发文章 毕业论文_研究生一天读多少文献-程序员宅基地

文章浏览阅读2.1k次,点赞3次,收藏13次。研究生论文写作步骤1. 先看综述,后看论著。看综述搞清概念,看论著掌握方法。2. 早动手在师兄师姐离开之前学会关键技术。3. 多数文章看摘要,少数文章看全文。掌握了一点查全文的技巧,往往会以搞到全文为乐,以至于没有时间看文章的内容,更不屑于看摘要。真正有用的全文并不多,过分追求全文是浪费,不可走极端。当然只看摘要也是不对的。4. 集中时间看文献,看过总会遗忘。看文献的时间越分散_研究生一天读多少文献

微光app电脑版_智米电暖器智能版1S体验:全面领跑AIoT、将智能生活进行到底-程序员宅基地

文章浏览阅读547次。【科技犬体验】2019年10月15日,智米正式推出了旗下电暖器新品——智米电暖器1S和智米电暖器智能版1S对于没有集中供暖的长江中下游地区居民而言,电暖器是不折不扣的"保命神器"。而在深秋的北方,昼夜温差较大,这种时候使用灵活、易于搬运的电暖器也成为更加明智的选择。在北方每年的冬季,室内温度就直接关系着大家在家的舒适度,而对于室内温度不达标的用户,购买电暖器就成为几乎唯一的选择。科技犬已经入手智米..._智米电暖器智能版app

《Hadoop与大数据挖掘》——2.6 TF-IDF算法原理及Hadoop MapReduce实现-程序员宅基地

文章浏览阅读312次。本节书摘来自华章计算机《Hadoop与大数据挖掘》一书中的第2章,第2.6节,作者 张良均 樊哲 位文超 刘名军 许国杰 周龙 焦正升,更多章节内容可以访问云栖社区“华章计算机”公众号查看。2.6 TF-IDF算法原理及Hadoop MapReduce实现2.6.1 TF-IDF算法原理原理:在一份给定的文件里,词频(Term Frequency,..._hadoop mapreduce如何实现实现tf-idf

Layui实现点击文字、缩略图查看图片功能_layui查看图片-程序员宅基地

文章浏览阅读4.3k次。刚完成一个客户需求,同一个页面上要有点击缩略图查看大图功能,也有点击图片名称查看原图的功能。点击缩略图查看大图的功能点击缩略图查看大图的功能实现用的是layui开发文档内的layer.photos-相册层。官方开发文档里photos支持传入json和直接读取页面图片两种方式。下面是官方开发文档的截图,官方开发文档链接:https://www.layui.com/doc/m..._layui查看图片

ueditor的配置和使用-程序员宅基地

文章浏览阅读89次。ueditor下载好之后直接复制到项目的WebContent目录下,并将ueditor\jsp\lib下的jar包复制或者剪切到项目的lib目录下。先看一下效果,如下:v1.文件的上传   首先在ueditor/jsp目录下找到config.json文件,就拿Image上传来说吧。  "imageUrlPrefix": "http:/..._ueditor json = new function("return " + result)();

20、NanoDet训练、测试 以及使用ncnn部署Jetson Nano 进行目标检测和串口数据转发-程序员宅基地

文章浏览阅读6.5k次,点赞7次,收藏59次。基本思想:最近想尝试一下nano 上部署nanodet,于是记录一下训练过程,手中有一份labelme标注的数据集,于是开始了一波操作~首先将图片和json数据集转成xml (https://blog.csdn.net/sxj731533730/article/details/90046780),然后将xml数据集转成voc;import sysimport osimport jsonimport xml.etree.ElementTree as ETfrom PIL import Im_nanodet

随便推点

乌龙(一)ntp对时_ntp对时 时区-程序员宅基地

文章浏览阅读107次。emmm…今天新搭了一套虚拟机(安装时一步过了 啥也没配置),操作时发现系统时间一直不对,于是安装了ntp跟阿里云等时钟源对过,发现一对时系统就变成了昨天,我把系统时间强制改为了现在,再次对时,时间又回退到昨天,最后发现时区选错了,选成了PST。解决方法cp -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime..._ntp对时 时区

数据结构_实验三_二叉树的基本操作_二叉树叶子节点实验-程序员宅基地

文章浏览阅读6.3k次,点赞18次,收藏81次。1.需求分析1.1 输入数据建立二叉树,分别以前序、中序、后序的遍历方式显示输出二叉树的遍历结果。输入输出形式:124$$5$3$$preOrder1 2 4 5 3inOrder4 2 5 1 3afterOrder4 5 2 3 1功能:利用树存储数据,采用递归的方式做到先序、中序、后序三种遍历方式输出数据范围:0~9测试数据:    124$$5$3$$      ..._二叉树叶子节点实验

P5738 【深基7.例4】歌唱比赛-程序员宅基地

文章浏览阅读311次。题目描述n(n\le 100)n(n≤100)名同学参加歌唱比赛,并接受m(m\le 20)m(m≤20)名评委的评分,评分范围是 0 到 10 分。这名同学的得分就是这些评委给分中去掉一个最高分,去掉一个最低分,剩下m-2m−2个评分的平均数。请问得分最高的同学分数是多少?评分保留 2 位小数。输入格式无输出格式无输入输出样例输入 ..._【深基7.例4】歌唱比赛

Vue简明实用教程(04)——事件处理_vue html里面如何直接写事件函数-程序员宅基地

文章浏览阅读1.1k次,点赞4次,收藏5次。在Vue中可非常便利地进行事件处理,例如:点击事件、鼠标悬停事件等。_vue html里面如何直接写事件函数

南京邮电大学离散数学实验一(求主析取和主合取范式)-程序员宅基地

文章浏览阅读4.5k次,点赞15次,收藏67次。南京邮电大学离散数学实验一(求主析取和主合取范式)_离散数学实验

{spring.cloud.client.ipAddress}_spring.cloud.client.ip-address-程序员宅基地

文章浏览阅读1.5w次,点赞2次,收藏5次。1.在springcloud中服务的 Instance ID 默认值是:${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}},也就是:主机名:应用名:应用端口。如图12.可以自定义:eureka.instance...._spring.cloud.client.ip-address

推荐文章

热门文章

相关标签