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控制部分的開銷測試