zoukankan      html  css  js  c++  java
  • Java中用内存映射处理大文件

    在处理大文件时,如果利用普通的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.       
    14.     public static void main(String[] args) {  
    15.         try {  
    16.             FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");  
    17.             int sum=0;  
    18.             int n;  
    19.             long t1=System.currentTimeMillis();  
    20.             try {  
    21.                 while((n=fis.read())>=0){  
    22.                     sum+=n;  
    23.                 }  
    24.             } catch (IOException e) {  
    25.                 // TODO Auto-generated catch block  
    26.                 e.printStackTrace();  
    27.             }  
    28.             long t=System.currentTimeMillis()-t1;  
    29.             System.out.println("sum:"+sum+"  time:"+t);  
    30.         } catch (FileNotFoundException e) {  
    31.             // TODO Auto-generated catch block  
    32.             e.printStackTrace();  
    33.         }  
    34.           
    35.         try {  
    36.             FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");  
    37.             BufferedInputStream bis=new BufferedInputStream(fis);  
    38.             int sum=0;  
    39.             int n;  
    40.             long t1=System.currentTimeMillis();  
    41.             try {  
    42.                 while((n=bis.read())>=0){  
    43.                     sum+=n;  
    44.                 }  
    45.             } catch (IOException e) {  
    46.                 // TODO Auto-generated catch block  
    47.                 e.printStackTrace();  
    48.             }  
    49.             long t=System.currentTimeMillis()-t1;  
    50.             System.out.println("sum:"+sum+"  time:"+t);  
    51.         } catch (FileNotFoundException e) {  
    52.             // TODO Auto-generated catch block  
    53.             e.printStackTrace();  
    54.         }  
    55.           
    56.         MappedByteBuffer buffer=null;  
    57.         try {  
    58.             buffer=new RandomAccessFile("/home/tobacco/test/res.txt","rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 1253244);  
    59.             int sum=0;  
    60.             int n;  
    61.             long t1=System.currentTimeMillis();  
    62.             for(int i=0;i<1253244;i++){  
    63.                 n=0x000000ff&buffer.get(i);  
    64.                 sum+=n;  
    65.             }  
    66.             long t=System.currentTimeMillis()-t1;  
    67.             System.out.println("sum:"+sum+"  time:"+t);  
    68.         } catch (FileNotFoundException e) {  
    69.             // TODO Auto-generated catch block  
    70.             e.printStackTrace();  
    71.         } catch (IOException e) {  
    72.             // TODO Auto-generated catch block  
    73.             e.printStackTrace();  
    74.         }  
    75.   
    76.     }  
    77.   
    78. }  


        测试文件为一个大小为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.       
    14.     public static void main(String[] args) {  
    15.         try {  
    16.             FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");  
    17.             int sum=0;  
    18.             int n;  
    19.             long t1=System.currentTimeMillis();  
    20.             try {  
    21.                 while((n=fis.read())>=0){  
    22.                     //sum+=n;  
    23.                 }  
    24.             } catch (IOException e) {  
    25.                 // TODO Auto-generated catch block  
    26.                 e.printStackTrace();  
    27.             }  
    28.             long t=System.currentTimeMillis()-t1;  
    29.             System.out.println("sum:"+sum+"  time:"+t);  
    30.         } catch (FileNotFoundException e) {  
    31.             // TODO Auto-generated catch block  
    32.             e.printStackTrace();  
    33.         }  
    34.           
    35.         try {  
    36.             FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");  
    37.             BufferedInputStream bis=new BufferedInputStream(fis);  
    38.             int sum=0;  
    39.             int n;  
    40.             long t1=System.currentTimeMillis();  
    41.             try {  
    42.                 while((n=bis.read())>=0){  
    43.                     //sum+=n;  
    44.                 }  
    45.             } catch (IOException e) {  
    46.                 // TODO Auto-generated catch block  
    47.                 e.printStackTrace();  
    48.             }  
    49.             long t=System.currentTimeMillis()-t1;  
    50.             System.out.println("sum:"+sum+"  time:"+t);  
    51.         } catch (FileNotFoundException e) {  
    52.             // TODO Auto-generated catch block  
    53.             e.printStackTrace();  
    54.         }  
    55.           
    56.         MappedByteBuffer buffer=null;  
    57.         try {  
    58.             buffer=new RandomAccessFile("/home/tobacco/test/res.txt","rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 1253244);  
    59.             int sum=0;  
    60.             int n;  
    61.             long t1=System.currentTimeMillis();  
    62.             for(int i=0;i<1253244;i++){  
    63.                 //n=0x000000ff&buffer.get(i);  
    64.                 //sum+=n;  
    65.             }  
    66.             long t=System.currentTimeMillis()-t1;  
    67.             System.out.println("sum:"+sum+"  time:"+t);  
    68.         } catch (FileNotFoundException e) {  
    69.             // TODO Auto-generated catch block  
    70.             e.printStackTrace();  
    71.         } catch (IOException e) {  
    72.             // TODO Auto-generated catch block  
    73.             e.printStackTrace();  
    74.         }  
    75.   
    76.     }  
    77.   
    78. }  


        测试结果:

    sum:0  time:1458
    sum:0  time:67
    sum:0  time:8

        由此可见,将文件部分或者全部映射到内存后进行读写,速度将提高很多。

        这是因为内存映射文件首先将外存上的文件映射到内存中的一块连续区域,被当成一个字节数组进行处理,读写操作直接对内存进行操作,而后再将内存区域重新映射到外存文件,这就节省了中间频繁的对外存进行读写的时间,大大降低了读写时间。

  • 相关阅读:
    2015年要做的150件事
    再见2014,你好2015
    页面滚动事件的使用
    简单的进度条演示
    mybatis foreach批量处理
    mysql执行顺序
    spring声明式事务 同一类内方法调用事务失效
    Semaphore
    springmvc使用JSR-303对复杂对象进行校验
    springmvc全局异常后返回JSON异常数据
  • 原文地址:https://www.cnblogs.com/sikewang/p/5564760.html
Copyright © 2011-2022 走看看