Java中用內(nèi)存映射處理大文件的實現(xiàn)代碼
在處理大文件時,如果利用普通的FileInputStream 或者FileOutputStream 抑或RandomAccessFile 來進行頻繁的讀寫操作,都將導致進程因頻繁讀寫外存而降低速度.如下為一個對比實驗。
package test;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class Test {
public static void main(String[] args) {
try {
FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");
int sum=0;
int n;
long t1=System.currentTimeMillis();
try {
while((n=fis.read())>=0){
sum+=n;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long t=System.currentTimeMillis()-t1;
System.out.println("sum:"+sum+" time:"+t);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");
BufferedInputStream bis=new BufferedInputStream(fis);
int sum=0;
int n;
long t1=System.currentTimeMillis();
try {
while((n=bis.read())>=0){
sum+=n;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long t=System.currentTimeMillis()-t1;
System.out.println("sum:"+sum+" time:"+t);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MappedByteBuffer buffer=null;
try {
buffer=new RandomAccessFile("/home/tobacco/test/res.txt","rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 1253244);
int sum=0;
int n;
long t1=System.currentTimeMillis();
for(int i=0;i<1253244;i++){
n=0x000000ff&buffer.get(i);
sum+=n;
}
long t=System.currentTimeMillis()-t1;
System.out.println("sum:"+sum+" time:"+t);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
測試文件為一個大小為1253244字節(jié)的文件。測試結(jié)果:
sum:220152087 time:1464
sum:220152087 time:72
sum:220152087 time:25
說明讀數(shù)據(jù)無誤。刪去其中的數(shù)據(jù)處理部分。
package test;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class Test {
public static void main(String[] args) {
try {
FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");
int sum=0;
int n;
long t1=System.currentTimeMillis();
try {
while((n=fis.read())>=0){
//sum+=n;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long t=System.currentTimeMillis()-t1;
System.out.println("sum:"+sum+" time:"+t);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");
BufferedInputStream bis=new BufferedInputStream(fis);
int sum=0;
int n;
long t1=System.currentTimeMillis();
try {
while((n=bis.read())>=0){
//sum+=n;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long t=System.currentTimeMillis()-t1;
System.out.println("sum:"+sum+" time:"+t);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MappedByteBuffer buffer=null;
try {
buffer=new RandomAccessFile("/home/tobacco/test/res.txt","rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 1253244);
int sum=0;
int n;
long t1=System.currentTimeMillis();
for(int i=0;i<1253244;i++){
//n=0x000000ff&buffer.get(i);
//sum+=n;
}
long t=System.currentTimeMillis()-t1;
System.out.println("sum:"+sum+" time:"+t);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
測試結(jié)果:
sum:0 time:1458
sum:0 time:67
sum:0 time:8
由此可見,將文件部分或者全部映射到內(nèi)存后進行讀寫,速度將提高很多。
這是因為內(nèi)存映射文件首先將外存上的文件映射到內(nèi)存中的一塊連續(xù)區(qū)域,被當成一個字節(jié)數(shù)組進行處理,讀寫操作直接對內(nèi)存進行操作,而后再將內(nèi)存區(qū)域重新映射到外存文件,這就節(jié)省了中間頻繁的對外存進行讀寫的時間,大大降低了讀寫時間。
以上這篇Java中用內(nèi)存映射處理大文件的實現(xiàn)代碼就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
java向mysql插入數(shù)據(jù)亂碼問題的解決方法
這篇文章主要為大家詳細介紹了java向mysql插入數(shù)據(jù)亂碼問題的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-09-09
Java 線程池ThreadPoolExecutor源碼解析
這篇文章主要介紹了Java 線程池ThreadPoolExecutor源碼解析2022-03-03
springboot整合mybatis-plus實現(xiàn)多表分頁查詢的示例代碼
這篇文章主要介紹了springboot整合mybatis-plus實現(xiàn)多表分頁查詢的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03
解決springboot 多線程使用MultipartFile讀取excel文件內(nèi)容報錯問題
這篇文章主要介紹了解決springboot 多線程使用MultipartFile讀取excel文件內(nèi)容報錯問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
Spring?Data?JPA查詢方式及方法名查詢規(guī)則介紹
這篇文章主要介紹了Spring?Data?JPA查詢方式及方法名查詢規(guī)則,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
springboot快速搭建ftpserver服務端的詳細步驟
基于springboot,使用ftpserver快速搭建一個FTP服務端,搭建過程很簡單,我們把過程分成4個步驟,一分鐘內(nèi)快速完成構(gòu)建,感興趣的朋友跟隨小編一起看看吧2023-11-11
淺談SpringBoot實現(xiàn)異步調(diào)用的幾種方式
本文主要介紹了淺談SpringBoot實現(xiàn)異步調(diào)用的幾種方式,主要包括CompletableFuture異步任務,基于@Async異步任務, TaskExecutor異步任務,感興趣的可以了解一下2023-11-11

