首页 > 代码库 > Java使用内存映射实现大文件的上传
Java使用内存映射实现大文件的上传
转自http://www.codeceo.com/article/java-big-file-upload.html
在处理大文件时,如果利用普通的FileInputStream 或者FileOutputStream 抑或RandomAccessFile 来进行频繁的读写操作,都将导致进程因频繁读写外存而降低速度.如下为一个对比实验。
1 package test; 2 3 import java.io.BufferedInputStream; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.IOException; 7 import java.io.RandomAccessFile; 8 import java.nio.MappedByteBuffer; 9 import java.nio.channels.FileChannel; 10 11 public class Test { 12 13 public static void main(String[] args) { 14 try { 15 FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt"); 16 int sum=0; 17 int n; 18 long t1=System.currentTimeMillis(); 19 try { 20 while((n=fis.read())>=0){ 21 sum+=n; 22 } 23 } catch (IOException e) { 24 // TODO Auto-generated catch block 25 e.printStackTrace(); 26 } 27 long t=System.currentTimeMillis()-t1; 28 System.out.println("sum:"+sum+" time:"+t); 29 } catch (FileNotFoundException e) { 30 // TODO Auto-generated catch block 31 e.printStackTrace(); 32 } 33 34 try { 35 FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt"); 36 BufferedInputStream bis=new BufferedInputStream(fis); 37 int sum=0; 38 int n; 39 long t1=System.currentTimeMillis(); 40 try { 41 while((n=bis.read())>=0){ 42 sum+=n; 43 } 44 } catch (IOException e) { 45 // TODO Auto-generated catch block 46 e.printStackTrace(); 47 } 48 long t=System.currentTimeMillis()-t1; 49 System.out.println("sum:"+sum+" time:"+t); 50 } catch (FileNotFoundException e) { 51 // TODO Auto-generated catch block 52 e.printStackTrace(); 53 } 54 55 MappedByteBuffer buffer=null; 56 try { 57 buffer=new RandomAccessFile("/home/tobacco/test/res.txt","rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 1253244); 58 int sum=0; 59 int n; 60 long t1=System.currentTimeMillis(); 61 for(int i=0;i<1253244;i++){ 62 n=0x000000ff&buffer.get(i); 63 sum+=n; 64 } 65 long t=System.currentTimeMillis()-t1; 66 System.out.println("sum:"+sum+" time:"+t); 67 } catch (FileNotFoundException e) { 68 // TODO Auto-generated catch block 69 e.printStackTrace(); 70 } catch (IOException e) { 71 // TODO Auto-generated catch block 72 e.printStackTrace(); 73 } 74 75 } 76 77 }
测试文件为一个大小为1253244字节的文件。测试结果:
sum:220152087 time:1464 sum:220152087 time:72 sum:220152087 time:25
说明读数据无误。删去其中的数据处理部分。
1 package test; 2 3 import java.io.BufferedInputStream; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.IOException; 7 import java.io.RandomAccessFile; 8 import java.nio.MappedByteBuffer; 9 import java.nio.channels.FileChannel; 10 11 public class Test { 12 13 public static void main(String[] args) { 14 try { 15 FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt"); 16 int sum=0; 17 int n; 18 long t1=System.currentTimeMillis(); 19 try { 20 while((n=fis.read())>=0){ 21 //sum+=n; 22 } 23 } catch (IOException e) { 24 // TODO Auto-generated catch block 25 e.printStackTrace(); 26 } 27 long t=System.currentTimeMillis()-t1; 28 System.out.println("sum:"+sum+" time:"+t); 29 } catch (FileNotFoundException e) { 30 // TODO Auto-generated catch block 31 e.printStackTrace(); 32 } 33 34 try { 35 FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt"); 36 BufferedInputStream bis=new BufferedInputStream(fis); 37 int sum=0; 38 int n; 39 long t1=System.currentTimeMillis(); 40 try { 41 while((n=bis.read())>=0){ 42 //sum+=n; 43 } 44 } catch (IOException e) { 45 // TODO Auto-generated catch block 46 e.printStackTrace(); 47 } 48 long t=System.currentTimeMillis()-t1; 49 System.out.println("sum:"+sum+" time:"+t); 50 } catch (FileNotFoundException e) { 51 // TODO Auto-generated catch block 52 e.printStackTrace(); 53 } 54 55 MappedByteBuffer buffer=null; 56 try { 57 buffer=new RandomAccessFile("/home/tobacco/test/res.txt","rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 1253244); 58 int sum=0; 59 int n; 60 long t1=System.currentTimeMillis(); 61 for(int i=0;i<1253244;i++){ 62 //n=0x000000ff&buffer.get(i); 63 //sum+=n; 64 } 65 long t=System.currentTimeMillis()-t1; 66 System.out.println("sum:"+sum+" time:"+t); 67 } catch (FileNotFoundException e) { 68 // TODO Auto-generated catch block 69 e.printStackTrace(); 70 } catch (IOException e) { 71 // TODO Auto-generated catch block 72 e.printStackTrace(); 73 } 74 75 } 76 77 }
测试结果:
sum:0 time:1458 sum:0 time:67 sum:0 time:8
由此可见,将文件部分或者全部映射到内存后进行读写,速度将提高很多。
这是因为内存映射文件首先将外存上的文件映射到内存中的一块连续区域,被当成一个字节数组进行处理,读写操作直接对内存进行操作,而后再将内存区域重新映射到外存文件,这就节省了中间频繁的对外存进行读写的时间,大大降低了读写时间。
感谢作者,转自http://www.codeceo.com/article/java-big-file-upload.html
Java使用内存映射实现大文件的上传
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。