[轉]RandomAccessFile

RandomAccessFile利用file pointer(文件指針),能夠從給定的位置開始讀取所需的數據。
以下代碼:app

private static String importFile(String filePath, Long pos, int size) {
        StringBuffer strBuff = new StringBuffer();
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(filePath, "r");
            long totalSize = raf.length();
            if (pos >= totalSize) {
                return null;
            }
            raf.seek(pos);
            String line = null;
            int row = 0;
            while ((line = raf.readLine()) != null && row <= size - 1) {
                strBuff.append(new String(line.getBytes("iso-8859-1"), "GBK"));
                strBuff.append("\n");
                row++;
            }
            pos = raf.getFilePointer();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (raf != null) {
                try {
                    raf.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return strBuff.toString();

    }


如上代碼,起始位置pos爲字節數,假如咱們須要從某一行開始讀取所需的數據,除非你操做的文件的每一行的大小固定(即每一行的字節數是不變的),則能夠利用行數轉化爲相應字節數來讀取相應行的數據不然的話,只能一行行的讀取數據了。上述代碼中,pos = raf.getFilePointer()獲取下一行起始位置的字節數,保存該值則下次可直接利用raf.seek(pos)方法從該位置開始讀取數據。
    可是在實際的測試中發現,RandomAccessFile其其I/O性能較之其餘的的同類性能差距很大,經測試其耗時爲BufferedReader的幾十倍,嚴重影響了程序的運行效率。
 
查看RandomAccessFile的源碼:
 dom

    public class RandomAccessFile implements DataOutput, DataInput {
        public final byte readByte() throws IOException {
            int ch = this.read();
            if (ch < 0)
                throw new EOFException();
            return (byte) (ch);
        }

        public native int read() throws IOException;

        public final void writeByte(int v) throws IOException {
            write(v);
        }

        public native void write(int b) throws IOException;
    } 


RandomAccessFile每讀/寫一個字節就需對磁盤進行一次I/O操做。
 
而BufferedInputStream] 的源碼:性能

public class BufferedInputStream extends FilterInputStream {
        private static int defaultBufferSize = 2048;
        protected byte buf[];

        public BufferedInputStream(InputStream in, int size) {
            super(in);
            if (size <= 0) {
                throw new IllegalArgumentException("Buffer size <= 0");
            }
            buf = new byte[size];
        }

        public synchronized int read() throws IOException {
            ensureOpen();
            if (pos >= count) {
                fill();
                if (pos >= count)
                    return -1;
            }
            return buf[pos++] & 0xff; // 直接從BUF[]中讀取 
        }

        private void fill() throws IOException {
            if (markpos < 0)
                pos = 0;
            else if (pos >= buf.length)
                if (markpos > 0) {
                    int sz = pos - markpos;
                    System.arraycopy(buf, markpos, buf, 0, sz);
                    pos = sz;
                    markpos = 0;
                } else if (buf.length >= marklimit) {
                    markpos = -1;
                    pos = 0;
                } else {
                    int nsz = pos * 2;
                    if (nsz > marklimit)
                        nsz = marklimit;
                    byte nbuf[] = new byte[nsz];
                    System.arraycopy(buf, 0, nbuf, 0, pos);
                    buf = nbuf;
                }
            count = pos;
            int n = in.read(buf, pos, buf.length - pos);
            if (n > 0)
                count = n + pos;
        }
    } 

 
Buffered I/O putStream每讀/寫一個字節,若要操做的數據在BUF中,就直接對內存的buf[]進行讀/寫操做;不然從磁盤相應位置填充buf[],再直接對內存的buf[]進行讀/寫操做,絕大部分的讀/寫操做是對內存buf[]的操做。
 
內存存取時間單位是納秒級(10E-9),磁盤存取時間單位是毫秒級(10E-3), 一樣操做一次的開銷,內存比磁盤快了百萬倍。理論上能夠預見,即便對內存操做上萬次,花費的時間也遠少對於磁盤一次I/O的開銷。 顯而後者是經過增長位於內存的BUF存取,減小磁盤I/O的開銷,提升存取效率的,固然這樣也增長了BUF控制部分的開銷測試

相關文章
相關標籤/搜索