• Java读取大文件的操作【转】


    转自http://aronlulu.iteye.com/blog/1018370

    读取文件大小:1.45G 
    第一种,OldIO: 

    Java代码  收藏代码
    1. public static void oldIOReadFile() throws IOException{  
    2.     BufferedReader br = new BufferedReader(new FileReader("G://lily_947.txt"));  
    3.     PrintWriter pw = new PrintWriter("G://oldIO.tmp");  
    4.     char[] c = new char[100*1024*1024];  
    5.     for(;;){  
    6.         if(br.read(c)!=-1){  
    7.             pw.print(c);  
    8.         }else{  
    9.             break;  
    10.         }  
    11.     }  
    12.     pw.close();  
    13.     br.close();  
    14. }  


    耗时70.79s 


    第二种,newIO: 

    Java代码  收藏代码
    1. public static void newIOReadFile() throws IOException{  
    2.         FileChannel read = new RandomAccessFile("G://lily_947.txt","r").getChannel();  
    3.         FileChannel writer = new RandomAccessFile("G://newIO.tmp","rw").getChannel();  
    4.         ByteBuffer bb = ByteBuffer.allocate(200*1024*1024);  
    5.         while(read.read(bb)!=-1){  
    6.             bb.flip();  
    7.             writer.write(bb);  
    8.             bb.clear();  
    9.         }  
    10.         read.close();  
    11.         writer.close();  
    12.           
    13.     }  


    耗时47.24s 


    第三种,RandomAccessFile: 

    Java代码  收藏代码
    1. public static void randomReadFile() throws IOException{  
    2.         RandomAccessFile read = new RandomAccessFile("G://lily_947.txt","r");  
    3.         RandomAccessFile writer = new RandomAccessFile("G://random.tmp","rw");  
    4.         byte[] b = new byte[200*1024*1024];  
    5.         while(read.read(b)!=-1){  
    6.             writer.write(b);  
    7.         }  
    8.         writer.close();  
    9.         read.close();  
    10.     }  


    耗时46.65 

    第四种,MappedByteBuffer: 

    Java代码  收藏代码
    1. public static void mappedBuffer() throws IOException{  
    2.         FileChannel read = new FileInputStream("G://lily_947.txt").getChannel();  
    3.         FileChannel writer = new RandomAccessFile("G://buffer.tmp","rw").getChannel();  
    4.         long i = 0;  
    5.         long size = read.size()/30;  
    6.         ByteBuffer bb,cc = null;  
    7.         while(i<read.size()&&(read.size()-i)>size){  
    8.             bb = read.map(FileChannel.MapMode.READ_ONLY, i, size);  
    9.             cc = writer.map(FileChannel.MapMode.READ_WRITE, i, size);  
    10.             cc.put(bb);  
    11.             i+=size;  
    12.             bb.clear();  
    13.             cc.clear();  
    14.         }  
    15.         bb = read.map(FileChannel.MapMode.READ_ONLY, i, read.size()-i);  
    16.         cc.put(bb);  
    17.         bb.clear();  
    18.         cc.clear();  
    19.         read.close();  
    20.         writer.close();  
    21.           
    22.     }  


    耗时:36 

    前三种读法对应的资源占用图如下: 
    相对于最后一种内存直接映射方式前面的测试其实无意义,基本秒杀。。。。。 
    对于很大的文件直接分块映射时内存会不够,这是因为MappedByteBuffer未被释放造成的,sun未提供直接回收MappedByteBuffer区域的方法,这个时候有两种方法解决,第一种比较愚笨的: 

    Java代码  收藏代码
    1.           System.gc();   
    2.          System.runFinalization();   
    3.          try {  
    4.     Thread.sleep(3000);  
    5. catch (InterruptedException e) {  
    6.       
    7.     e.printStackTrace();  
    8. }  


    第二种网上找来的,利用反射调用clean方法: 

    Java代码  收藏代码
    1. public static void unmap(final MappedByteBuffer buffer) {  
    2.         if (buffer == null) {  
    3.             return;  
    4.         }  
    5.         AccessController.doPrivileged(new PrivilegedAction<Object>() {  
    6.             public Object run() {  
    7.                 try {  
    8.                     Method getCleanerMethod = buffer.getClass().getMethod("cleaner", new Class[0]);  
    9.                     if (getCleanerMethod != null) {  
    10.                         getCleanerMethod.setAccessible(true);  
    11.                         Object cleaner = getCleanerMethod.invoke(buffer, new Object[0]);  
    12.                         Method cleanMethod = cleaner.getClass().getMethod("clean", new Class[0]);  
    13.                         if (cleanMethod != null) {  
    14.                             cleanMethod.invoke(cleaner, new Object[0]);  
    15.                         }  
    16.                     }  
    17.                 } catch (Exception e) {  
    18.                     e.printStackTrace();  
    19.                 }  
    20.                 return null;  
    21.             }  
    22.    
    23.         });  
    24.     }  


    以上两种方法感觉都别扭,还有就是可以自己分割成物理文件再循环调用,这个也不太美观。 
    速度也会减慢好多。

  • 相关阅读:
    调用webservice接口报错
    Java设计模式之使用反序列化的方式实现单例模式
    Java设计模式之使用枚举类的方式创建单例
    使用饿汉模式创建单例模式
    Java 查看运行生成的字节码文件 反汇编
    Java设计模式之--单例模式-使用懒汉模式创建
    git无法 cherry pick到其他分支
    Android之Handler用法总结
    Java之观察者模式
    Android之Activity与Service通信
  • 原文地址:https://www.cnblogs.com/nightsu/p/5939002.html
Copyright © 2020-2023  润新知