WWW.LOUGH.COM.CN

加入收藏 | 设为首页 | 联系站长
首页 | Java | C&C++ | 数据库 | 经验交流
论坛首页 | 综合区 | 贴图区 | 狐朋狗友 | 学习区 | 站务区
博客首页 | IT技术 | WebServices | Hibernate | Java设计模式 | Struts | AJAX | 数据库
首页 | 中华古籍 | 网络原创 | 随记

提高JAVA的I/O性能

提高JAVA的I/O性能

在JDK1.0.2中,只有BufferedInputStream 和 BufferedOutputStream两个类提供了有缓冲
的I/O。而这两个类提供的方法的远远不够用的。大多数情况下,我们只能使用没有缓冲的
方法。在JDK1.1中,提供了Reader 和 Writer 两种父类,他们的子类都是有缓冲的,而且
提供了我们所需要的大部分方法。通过缓冲,我们可以得到10至20倍的性能。
   可惜的是,某些很有用的类,仍然没有提供缓冲,例如RandomAccessFile。所以在这
种情况下,我们有必要实现自己的缓冲。
   看看下面这个类: 
  public class Braf extends RandomAccessFile {

  }

   buffer是用作缓冲的byte数组;buf_end、buf_pos和real_pos用于记录buffer的位置


  byte buffer[];
  int buf_end = 0;
  int buf_pos = 0;
  long real_pos = 0;

   新的构造函数增加了参数bufsize,用于定义缓冲的大小。 
  public Braf(String filename, String mode, int bufsize) 
        throws IOException{
    super(filename,mode);
    invalidate();
    BUF_SIZE = bufsize;
    buffer = new byte[BUF_SIZE];    
  }

   新增的read方法总是从缓冲中读取资料,如果资料不在缓冲中,则调用fillBuffer方
法来更新缓冲区。而原来的的read方法则在fillBuffer中被调用。如果当前的文件指针所
指向的内容不在缓冲中,则invalidate()方法被调用。

  public final int read() throws IOException{
    if(buf_pos >= buf_end) {
            if(fillBuffer() < 0)
            return -1;
    }
    if(buf_end == 0) {
              return -1;
    } else {
              return buffer[buf_pos++];
    }
  }

  private int fillBuffer() throws IOException {
    int n = super.read(buffer, 0, BUF_SIZE);
    if(n >= 0) {
      real_pos +=n;
      buf_end = n;
      buf_pos = 0;
    }
    
    return n;
  }

  private void invalidate() throws IOException {
    buf_end = 0;
    buf_pos = 0;
    real_pos = super.getFilePointer();
  }

   为了提高效率,我们也重载了别的read方法。在这个read方法里,如果所需的内容都
在缓冲中,就调用System.arraycopy,把缓冲的内容直接拷贝到用户所提供的地方。

  public int read(byte b[], int off, int len) throws IOException {
        int leftover = buf_end - buf_pos;
        if(len <= leftover) {
             System.arraycopy(buffer, buf_pos, b, off, len);
             buf_pos += len;
             return len;
        }

        for(int i = 0; i < len; i++) {
                int c = this.read();
                if(c != -1)
                        b[off+i] = (byte)c;
                else {
                        return i;
                }
        }
        return len;
  }

   因为我们使用了缓冲技术,所以getFilePointer和seek方法都必须重写。在大多数情
况下,使用这两个方法都不必进行实际的I/O操作。

  public long getFilePointer() throws IOException{
    long l = real_pos;
    return (l - buf_end + buf_pos) ;
  }

  public void seek(long pos) throws IOException {
    int n = (int)(real_pos - pos);
    if(n >= 0 && n <= buf_end) {
      buf_pos = buf_end - n;
    } else {
      super.seek(pos);
      invalidate();
    }
  }

   由于在原来的类中readLine被定义为final,我们有必要写一个新的方法来充分发挥缓
冲的优势。这就是getNextLine。如果缓冲区不含所需资料,它会调用方法fillBuffer 来
更新缓冲区。然后读出相应的内容,转换成String,返回。因为使用了缓冲技术,它的性
能比原来的高很多。

  /**
   * return a next line in String 
   */
  public final String getNextLine() throws IOException {
        String str = null;

        if(buf_end-buf_pos <= 0) {
                if(fillBuffer() < 0) {
                     throw new IOException("error in filling buffer!");
                }
        }
                                 
        int lineend = -1;
        
        for(int i = buf_pos; i < buf_end; i++) {
                  if(buffer[i] == '\n') {
                        lineend = i;
                         break;
                    }
        }
        
        if(lineend < 0) {
             StringBuffer input = new StringBuffer(256);
             int c;

             while (((c = read()) != -1) && (c != '\n')) {
                      input.append((char)c);
             }
             if ((c == -1) && (input.length() == 0)) {
                    return null;
             }
             return input.toString();
        }

        if(lineend > 0 && buffer[lineend-1] == '\r')
             str = new String(buffer, 0, buf_pos, lineend - buf_pos -1);
        else str = new String(buffer, 0, buf_pos, lineend - buf_pos);
        
        buf_pos = lineend +1;
        return str;
   }



关于我们 | 站点地图 | 免责声明 | 联系我们 | ©2003-2007 Lough.com.cn 京ICP备06060948号