Java使用記憶體對映實現大檔案的上傳
在處理大檔案時,如果利用普通的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位元組的檔案。測試結果:
sum:220152087 time:1464 sum:220152087 time:72 sum:220152087 time:25
說明讀資料無誤。刪去其中的資料處理部分。
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(); } } }
測試結果:
sum:0 time:1458 sum:0 time:67 sum:0 time:8
由此可見,將檔案部分或者全部對映到記憶體後進行讀寫,速度將提高很多。
這是因為記憶體對映檔案首先將外存上的檔案對映到記憶體中的一塊連續區域,被當成一個位元組陣列進行處理,讀寫操作直接對記憶體進行操作,而後再將記憶體區域重新對映到外存檔案,這就節省了中間頻繁的對外存進行讀寫的時間,大大降低了讀寫時間。
相關文章
- Java記憶體對映,上G大檔案輕鬆處理Java記憶體
- 使用記憶體對映檔案(mmap)記憶體
- JAVA記憶體對映檔案實現多執行緒下載Java記憶體執行緒
- 記憶體對映檔案詳解-----C++實現(即一塊記憶體和一個檔案相對映對應)記憶體C++
- Python mmap的使用-檔案記憶體對映Python記憶體
- C#記憶體對映大檔案並使用Marshal解析結構體資訊C#記憶體結構體
- Java 中使用記憶體對映檔案需要考慮的 10 個問題Java記憶體
- 使用java的MultipartFile實現layui官網檔案上傳實現全部示例,java檔案上傳JavaUI
- VC++中用記憶體對映檔案 (轉)C++記憶體
- 二進位制檔案記憶體對映記憶體
- 一個記憶體檔案對映使用者類 (轉)記憶體
- windows核心程式設計--記憶體對映檔案Windows程式設計記憶體
- 居然這就是C++記憶體對映檔案?!C++記憶體
- JAVA實現大檔案分片上傳斷點續傳Java斷點
- 記憶體對映記憶體
- 非同步日誌 vs. 記憶體對映檔案非同步記憶體
- Win 95下記憶體對映檔案的工作原理及使用方法 (轉)記憶體
- mmap記憶體對映記憶體
- 短影片原始碼實現流式傳輸,降低處理大檔案時對記憶體的佔用原始碼記憶體
- Linux 記憶體管理:記憶體對映Linux記憶體
- Java檔案上傳如何實現呢?Java
- Java如何上傳大檔案Java
- 溫故之.NET程式間通訊——記憶體對映檔案記憶體
- java實現sftp檔案的上傳下載JavaFTP
- 使用Spring實現上傳檔案Spring
- C# .Net 多程式同步 通訊 共享記憶體 記憶體對映檔案 Memory MappedC#記憶體APP
- 使用webuploader元件實現大檔案分片上傳,斷點續傳Web元件斷點
- AngularJS實現的檔案檔案上傳AngularJS
- java記憶體模型的實現Java記憶體模型
- ajax實現檔案上傳
- 用java+ftp實現檔案上傳的問題?JavaFTP
- PHP實現單檔案、多檔案上傳 封裝 物件導向實現檔案上傳PHP封裝物件
- 大檔案上傳實踐分享
- 使用Spring Boot實現檔案上傳功能Spring Boot
- js實現帶上傳進度的檔案上傳JS
- java 讀 大檔案excel 記憶體溢位 解決JavaExcel記憶體溢位
- 【IPC程式間通訊之三】記憶體對映檔案Mapping FileC程式記憶體APP
- Java大檔案上傳、分片上傳、多檔案上傳、斷點續傳、上傳檔案minio、分片上傳minio等解決方案Java斷點