zoukankan      html  css  js  c++  java
  • [转]RandomAccessFile

    RandomAccessFile利用file pointer(文件指针),可以从给定的位置开始读取所需的数据。
    如下代码:

    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("
    ");
                    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的源码:
     

        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控制部分的开销

  • 相关阅读:
    索引总结篇
    数据库的安全管理
    数据库备份对日志文件的影响
    数据文件与日志文件读取机制
    更新操作所带来的影响
    页拆分-产生碎片
    你不可不知的T-SQL执行顺序
    实用T-SQL收集
    Left Join的神奇效果
    我对数据库索引的理解
  • 原文地址:https://www.cnblogs.com/wukong0214/p/3331604.html
Copyright © 2011-2022 走看看