Java IO和NIO读取大文件,对比速度

Java IO和NIO读取大文件,对比速度

话题:假设机器只有500M内存,有一个1.23GB的文件,要从一个目录复制到另外一个目录

目的:比较IO与NIO的读取速度效率

细节:大文件不能一次读到内存中,否则会内存溢出,只能每次读取固定大小的数据流

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

文件大小 1.23GB

1.使用RandomAccessFile读取文件,FileOutputStream写文件,耗时:8768ms

2.使用BufferedInputStream读取文件,BufferedOutputStream写文件,耗时:2202ms

3.使用Scanner读文件,FileOutputStream写文件,耗时:120945ms

4.使用NIO,FileChannel读写文件,耗时:

NIO每次读取1M,耗时:8947msNIO每次读取5M,耗时:2976msNIO每次读取10M,耗时:1802msNIO每次读取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();

}

}

}

}

🎎 相关推荐

快速修复:U盘在电视上读不出来怎么办?
🎯 365bet娱乐app

快速修复:U盘在电视上读不出来怎么办?

📅 06-30 👀 1967
《海贼无双3》白金思路
🎯 365bet地址

《海贼无双3》白金思路

📅 06-29 👀 9436
新买的铸铁锅该怎么开锅?做好这些步骤就能把锅养好