Java中用内存映射处理大文件

在处理大文件时,如果利用普通的FileInputStream 或者FileOutputStream 抑或RandomAccessFile 来进行频繁的读写操作,都将导致进程因频繁读写外存而降低速度.如下为一个对比实验。

  1. package test;  
  2. import java.io.BufferedInputStream;  
  3. import java.io.FileInputStream;  
  4. import java.io.FileNotFoundException;  
  5. import java.io.IOException;  
  6. import java.io.RandomAccessFile;  
  7. import java.nio.MappedByteBuffer;  
  8. import java.nio.channels.FileChannel;  
  9. public class Test {  
  10.       
  11.     public static void main(String[] args) {  
  12.         try {  
  13.             FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");  
  14.             int sum=0;  
  15.             int n;  
  16.             long t1=System.currentTimeMillis();  
  17.             try {  
  18.                 while((n=fis.read())>=0){  
  19.                     sum+=n;  
  20.                 }  
  21.             } catch (IOException e) {  
  22.                 // TODO Auto-generated catch block 
  23.                 e.printStackTrace();  
  24.             }  
  25.             long t=System.currentTimeMillis()-t1;  
  26.             System.out.println("sum:"+sum+"  time:"+t);  
  27.         } catch (FileNotFoundException e) {  
  28.             // TODO Auto-generated catch block 
  29.             e.printStackTrace();  
  30.         }  
  31.           
  32.         try {  
  33.             FileInputStream fis=new FileInputStream("/home/tobacco/test/res.txt");  
  34.             BufferedInputStream bis=new BufferedInputStream(fis);  
  35.             int sum=0;  
  36.             int n;  
  37.             long t1=System.currentTimeMillis();  
  38.             try {  
  39.                 while((n=bis.read())>=0){  
  40.                     sum+=n;  
  41.                 }  
  42.             } catch (IOException e) {  
  43.                 // TODO Auto-generated catch block 
  44.                 e.printStackTrace();  
  45.             }  
  46.             long t=System.currentTimeMillis()-t1;  
  47.             System.out.println("sum:"+sum+"  time:"+t);  
  48.         } catch (FileNotFoundException e) {  
  49.             // TODO Auto-generated catch block 
  50.             e.printStackTrace();  
  51.         }  
  52.           
  53.         MappedByteBuffer buffer=null;  
  54.         try {  
  55.             buffer=new RandomAccessFile("/home/tobacco/test/res.txt","rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 1253244);  
  56.             int sum=0;  
  57.             int n;  
  58.             long t1=System.currentTimeMillis();  
  59.             for(int i=0;i<1253244;i++){  
  60.                 n=0x000000ff&buffer.get(i);  
  61.                 sum+=n;  
  62.             }  
  63.             long t=System.currentTimeMillis()-t1;  
  64.             System.out.println("sum:"+sum+"  time:"+t);  
  65.         } catch (FileNotFoundException e) {  
  66.             // TODO Auto-generated catch block 
  67.             e.printStackTrace();  
  68.         } catch (IOException e) {  
  69.             // TODO Auto-generated catch block 
  70.             e.printStackTrace();  
  71.         }  
  72.     }  
  73. }

  测试文件为一个大小为1253244字节的文件。测试结果:

  1. sum:220152087 time:1464  
  2. sum:220152087 time:72  
  3. 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. }

  测试结果:

  1. sum:0 time:1458  
  2. sum:0 time:67  
  3. sum:0 time:8

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

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

====================================分割线================================

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-08-17 05:59:27

Java中用内存映射处理大文件的相关文章

Java中用内存映射处理大文件的实现代码_java

在处理大文件时,如果利用普通的FileInputStream 或者FileOutputStream 抑或RandomAccessFile 来进行频繁的读写操作,都将导致进程因频繁读写外存而降低速度.如下为一个对比实验. package test; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOExc

Java中使用内存映射实现大文件上传实例_java

在处理大文件时,如果利用普通的FileInputStream 或者FileOutputStream 抑或RandomAccessFile 来进行频繁的读写操作,都将导致进程因频繁读写外存而降低速度.如下为一个对比实验. 复制代码 代码如下: package test;  import java.io.BufferedInputStream;  import java.io.FileInputStream;  import java.io.FileNotFoundException;  impor

内存映射修改大文件

本文介绍利用内存映射文件修改大文件:在大文件内存前加入一段数据,若要使用内存映射文件,必须执行下列操作步骤: 创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件: 创建一个文件映射内核对象,告诉系统该文件的大小和你打算如何访问该文件: 让系统将文件映射对象的全部或一部分映射到你的进程地址空间中: 当完成对内存映射文件的使用时,必须执行下面这些步骤将它清除: 告诉系统从你的进程的地址空间中撤消文件映射内核对象的映像: 关闭文件映射内核对象: 关闭文件内核对象: 下面将用一个

内存映射-读取大文件时遇到的问题

问题描述 读取大文件时遇到的问题 用readfile()函数也好,用内存映射的方式也好,怎么读取的数据都只是文件第一行?其他的都读取不到?不知道错在哪里,谢谢您的回答! 解决方案 应该要遍历去读取吧?不知道你怎么在弄... 解决方案二: 你可能只指定了第一行,没有遍历去指定行.把代码贴出来看看 解决方案三: 你是不是用了strtok. 它会把原字符串的分隔符替换成/0

java 通过apache ftp读取大文件或者下载大文件

问题描述 java 通过apache ftp读取大文件或者下载大文件 本人技术短,参照网上各位大侠的帖子写了登录ftp去读取ftp下面文件然后直接存进数据库的代码 ,但是我的代码只能读取一些小的文件,文件大点就报内存溢出.谁可以给个能在ftp上面下载大文件或者能够直接读取ftp服务器上面的大文件然后直接解析存进数据库的代码例子.不胜感激. 解决方案 内存溢出..说明内存方步下文件..ftp取到liu后写入文件吧...ps都内存溢出了..你不可能在内存中解析的..有可能是你jvm内存设置太小所致.

mongodb mmap内存映射是把文件中数据全部映射到内存中的吗?

问题描述 mongodb mmap内存映射是把文件中数据全部映射到内存中的吗? 资料上说:在Mongodb中,其使用了操作系统底层提供的内存映射机制,即MMAP.MMAP可以把磁盘文件的一部分或全部内容直接映射到内存,这样文件中的信息位置就会在内存中有对应的地址空间,这时对文件的读写可以直接用指针来做,而不需要read/write函数了.同时操作系统会将数据刷新保存到磁盘上. 我有个疑问:这个内存映射,是把文件中数据全部映射到内存中的吗?还是只是映射一部分内容,那么这部门内容又是什么的呢? 请专

Java实现按行读取大文件_java

Java实现按行读取大文件 String file = "F:" + File.separator + "a.txt"; FileInputStream fis = new FileInputStream(file); RandomAccessFile raf = new RandomAccessFile(new File(file),"r"); String s ; while((s =raf.readLine())!=null){ Syste

Java如何高效的读取大文件实例教程

       1.概述 本教程将演示如何用Java高效地读取大文件,这些大文件操作虽然不是很常用,但是如果有项目要用到的话就有用武之地了. 2.在内存中读取 读取文件行的标准方式是在内存中读取,Guava 和Apache Commons IO都提供了如下所示快速读取文件行的方法: Files.readLines(new File(path), Charsets.UTF_8); FileUtils.readLines(new File(path)); 这种方法带来的问题是文件的所有行都被存放在内存

浅析php中如何在有限的内存中读取大文件_php技巧

正常情况下,我们可以使用fseek来读取,好处就是不会一次性读取,以下代码只适合边取边处理的情况,不适合一次性读取一次性处理.可以用以下办法生成测试文件 复制代码 代码如下: $file_handle = fopen("./csdn.txt", "rb+");for ($index1 = 1; $index1 <= 2000000; $index1++) {    fwrite($file_handle, 'http://jb51.net'.$index1.&