JAVA之NIO按行讀取大文件


        做項目過程中遇到要解析100多M的TXT文件,並入庫。用之前的FileInputStream、BufferedReader顯然不行了,雖然readLine這方法可以直接按行讀取,但是去讀一個140M左右,68W條數據的文件時,不但耗時長而且會內存溢出,即你等不到讀完68W條數據時就內存溢出了。所以得用NIO下面的相關對象及方法。

       用到 字節緩沖區(Java.nio.ByteBuffer);用於讀取、寫入、映射和操作文件的通道( java.nio.channels.FileChannel);設置文本字條集(java.nio.charset.Charset);支持對隨機存取文件的讀取和寫入(java.io.RandomAccessFile)。

       具體思路是:設置兩個緩沖區,一大一小,大的緩沖區為每次讀取的量,小的緩沖區存放每行的數據(確保大小可存放文本中最長的那行)。讀取的時候判斷是不是換行符13,是的話則返回一行數據,不是的話繼續讀取,直到讀完文件。

       實現方法:

        FileChannel fc=raf.getChannel();

       //一次讀取文件,讀取的字節緩存數
       ByteBuffer fbb=ByteBuffer.allocate(1024*5);
        fc.read(fbb);
        fbb.flip();

     //每行緩存的字節   根據你的實際需求     

      ByteBuffer bb=ByteBuffer.allocate(500);

   

              //判斷是否讀完文件

public boolean hasNext() throws IOException {

        if(EOF)return false;
        if(fbb.position()==fbb.limit()){//判斷當前位置是否到了緩沖區的限制
            if(readByte()==0)  return false;
        }
        while(true){
            if(fbb.position()==fbb.limit()){
                if(readByte()==0)  break;
            }
            byte a=fbb.get();
            if(a==13){
                if(fbb.position()==fbb.limit()){
                    if(readByte()==0)  break;
                }
                return true;
            }else{
                if (bb.position() < bb.limit()) {
                    bb.put(a);
                }else {
                    if(readByte()==0)  break;
                }
            }
        }
        return true;
    }

private int readByte() throws IOException{
        //使緩沖區做好了重新讀取已包含的數據的准備:它使限制保持不變,並將位置設置為零。 
        fbb.rewind();
        //使緩沖區做好了新序列信道讀取或相對 get 操作的准備:它將限制設置為當前位置,然后將該位置設置為零。 
        fbb.clear();
        if(this.fc.read(fbb)==-1){ 
            EOF=true;
            return 0;
        }else{
            fbb.flip();
            return fbb.position();
        }
    }

    public byte[] next(){
        bb.flip();

        //此處很重要,返回byte數組方便,行被分割的情況下合並,否則如果正好達到緩沖區的限制時,一個中文漢字被拆了兩個字節,就會顯示不正常
        byte tm[] = Arrays.copyOfRange(bb.array(), bb.position(), bb.limit());
        bb.clear();
        return tm;
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM