注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

anqiang专栏

不要问细节是怎么搞的,源码说明一切

 
 
 

日志

 
 

RAMInputSteam源码分析  

2009-11-30 10:22:16|  分类: Lucene |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

 

RAMInputSteam是相对于RAMOutputSteam的,因此它的很多操作与RAMOutputSteam相同。

源码展示:

package org.apache.lucene.store;

import java.io.IOException;

/**

 * Licensed to the Apache Software Foundation (ASF) under one or more

 * contributor license agreements.  See the NOTICE file distributed with

 * this work for additional information regarding copyright ownership.

 * The ASF licenses this file to You under the Apache License, Version 2.0

 * (the "License"); you may not use this file except in compliance with

 * the License.  You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */

/**

 * A memory-resident {@link IndexInput} implementation.

 * 

 * @version $Id: RAMInputStream.java 632120 2008-02-28 21:13:59Z mikemccand $

 * Andrew Wang

 */

class RAMInputStream extends IndexInput implements Cloneable {

  static final int BUFFER_SIZE = RAMOutputStream.BUFFER_SIZE;

  private RAMFile file;

  private long length;

  private byte[] currentBuffer;

  private int currentBufferIndex;

  

  private int bufferPosition;

  private long bufferStart;

  private int bufferLength;

  

  RAMInputStream(RAMFile f) throws IOException {

    file = f;

    length = file.length;

    /**

     * Integer.MAX_VALUE = 2,147,483,647

     * 大概是需要2T的内存才能读入这样大的文件

     * 不过既然在RAMOutSteam中没有对这个参数进行判断,在这里进行判断又有什么意义?

     * 仅仅是对大家的一个提醒,这不是可以无限扩展的对象,

     * "我可是保存在内存中的啊",这段可能就是要表达这个意思

     */

    if (length/BUFFER_SIZE >= Integer.MAX_VALUE) {

      throw new IOException("Too large RAMFile! "+length); 

    }

    // make sure that we switch to the

    // first needed buffer lazily

    currentBufferIndex = -1;

    currentBuffer = null;

  }

  public void close() {

    // nothing to do here

  }

  public long length() {

    return length;

  }

  public byte readByte() throws IOException {

    if (bufferPosition >= bufferLength) {

      currentBufferIndex++;

      switchCurrentBuffer(true);

    }

    return currentBuffer[bufferPosition++];

  }

  /**

   * 与RAMOutputStream相似

   */

  public void readBytes(byte[] b, int offset, int len) throws IOException {

    while (len > 0) {

      if (bufferPosition >= bufferLength) {

        currentBufferIndex++;

        switchCurrentBuffer(true);

      }

      int remainInBuffer = bufferLength - bufferPosition;

      int bytesToCopy = len < remainInBuffer ? len : remainInBuffer;

      System.arraycopy(currentBufferbufferPosition, b, offset, bytesToCopy);

      offset += bytesToCopy;

      len -= bytesToCopy;

      bufferPosition += bytesToCopy;

    }

  }

  /**

   * 切换当前块

   * @param enforceEOF

   * @throws IOException

   */

  private final void switchCurrentBuffer(boolean enforceEOF) throws IOException {

    if (currentBufferIndex >= file.numBuffers()) {

      // end of file reached, no more buffers left

      if (enforceEOF)

        throw new IOException("Read past EOF");

      else {

        // Force EOF if a read takes place at this position

        currentBufferIndex--;

        bufferPosition = BUFFER_SIZE;

      }

    } else {

      currentBuffer = (byte[]) file.getBuffer(currentBufferIndex);

      bufferPosition = 0;

      bufferStart = (longBUFFER_SIZE * (longcurrentBufferIndex;

      long buflen = length - bufferStart;

      bufferLength = buflen > BUFFER_SIZE ? BUFFER_SIZE : (int) buflen;

    }

  }

  public long getFilePointer() {

    return currentBufferIndex < 0 ? 0 : bufferStart + bufferPosition;

  }

  /**

   * 定位当前pos指针位置

   */

  public void seek(long pos) throws IOException {

    if (currentBuffer==null || pos < bufferStart || pos >= bufferStart + BUFFER_SIZE) {

      currentBufferIndex = (int) (pos / BUFFER_SIZE);

      switchCurrentBuffer(false);

    }

    bufferPosition = (int) (pos % BUFFER_SIZE);

  }

}

RAMInputStream(RAMFile f) throws IOException

只有这个函数还有点意思,它会先判断一下,当前这个RAMFile的大小是否超过了一定范围大概在2T,如果超过2T将抛出异常。现在这个2T好像对于我们来说好遥远,也许在不久的将来它会是一个像现在的2G这么普遍的事实了。到那个时候也许代码就该变动了。

顺带说一句,以前我在工作和学习中对这个数值运算很不以为然,以为只要懂得了大概原理就OK了。例如:if (length/BUFFER_SIZE >= Integer.MAX_VALUE) 这一句,要是在以前,我仅仅知道这个file大小不能无限大。但是到底这个大小是多少,我不会去探究。这样的工作方式在学生生涯我沿用了很多年,可是在半年出来实习和应聘的过程中,我不断的遇到这样的问题“你处理的数据到底有多大?这个极限值到底是多少?”,这些问题难倒了我,因为我只知道原理。这些仅仅是一个抽象的东西,只有当把这些细节搞清楚,我们才能真正把握问题的实质。对于上面的问题,我通过计算知道,它的限制是2T,然后把它与现有内存的大小进行比对,就会有一个清晰的认识了。这就是有抽象到具体。是一个方法的问题,我学到了,并在实际的工作中经常这样做,不让自己眼高手低。

  评论这张
 
阅读(195)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017