• 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

  • 相关阅读:
    测试同学都应该知道的断言知识...
    自己如何修改Airtest的源码
    如何选择适合你的图像识别算法
    如何测试基于Unity3D引擎的游戏
    Web前端-按钮点击效果(水波纹)
    C# Email 帮助类 EmailHelper
    WinForm 加载大数据时不闪烁的ListView
    LZZ磁力资源搜索4.2.2,整合多个站点,大部分资源都能搜到
    C#7.0新特性和语法糖详解
    6种css3 transform图片悬停动态效果
  • 原文地址:https://www.cnblogs.com/ning1121/p/4220216.html
Copyright © 2020-2023  润新知