<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    csusky

    常用鏈接

    統計

    最新評論

    #

    org.apache.lucene.index.SegmentInfos

    final class SegmentInfos extends Vector
    可以看出該類實際上是一個Vector   以及封裝了對該Vevtor的一些操作
    實際上封裝的是對segments文件的一些讀寫操作
    先來看下segments文件的格式

    segments文件的格式:
    int:  =-1         文件是否是Lucene合法的文件格式正常情況下為 -1
    long:             版本號,每更新一次該文件將會將版本號加1
    int:                用來命名新段
    int:                段的數目
    String + int  段的信息 String是段的名稱  int是段中所含的doc數目
    String + int  同上

    所以用Lucene的API,我們可以簡單的打印出其segments的所有信息

    try {
       //DataInputStream fis = new DataInputStream(new FileInputStream("C:\\sf\\snow\\segments"));
       FSDirectory dir=FSDirectory.getDirectory("C:/sf/snow", false);
        InputStream input = dir.openFile("segments");
       System.out.println("Format:"+input.readInt());             //得到文件標志,是否為正常的segments文件
       System.out.println("version:"+input.readLong());        //得到版本號
       System.out.println("name:"+input.readInt());                //得到用來重命名新段的int,暫時不知道有什么用
       int n=input.readInt();                                                          //段的數目
       System.out.println("SegmentNum:"+n);                          
       for(int i=0;i<n;i++) {                                                           //用循環打印出所有段的信息 名稱和長度
        System.out.println("segment "+i+" - name:"+input.readString()+" num:"+input.readInt());
       }
      } catch (Exception e) {

      }
    當然,該類提供了更為復雜的訪問和更新segments文件的方法
     final void read(Directory directory)    將所有的段信息保存在本vector中
    final void write(Directory directory)    跟新該segment文件的內容,主要是為了添加段,
    主要是更新 版本號 段的數目,跟新完這些后即可往segment文件后添加新段的信息。

    posted @ 2008-04-18 17:02 曉宇 閱讀(365) | 評論 (0)編輯 收藏

    org.apache.lucene.index.SegmentInfo

    segment(段)的信息
    該類比較簡單,貼出其全部代碼

    import org.apache.lucene.store.Directory;

    final class SegmentInfo {
      public String name;        //在索引目錄中唯一的名稱 
      public int docCount;      // 該段中doc的數目
      public Directory dir;      // 該段所存在的Dirrectory

      public SegmentInfo(String name, int docCount, Directory dir) {
        this.name = name;
        this.docCount = docCount;
        this.dir = dir;
      }
    }

    posted @ 2008-04-18 16:45 曉宇 閱讀(265) | 評論 (0)編輯 收藏

    org.apache.lucene.store.RAMInputStream

    該類是從RAMFile中讀數據用的
    最重要的一個方法:
    該方法存在著從RAMFile的多個byte[1024]中讀取數據的情況,所以應該在循環中進行處理

     public void readInternal(byte[] dest, int destOffset, int len) {
        int remainder = len;
        int start = pointer;
        while (remainder != 0) {
          int bufferNumber = start/BUFFER_SIZE; //  buffer的序號
          int bufferOffset = start%BUFFER_SIZE; //    buffer偏移量
          int bytesInBuffer = BUFFER_SIZE - bufferOffset;// 在當前buffer中剩下的字節數
          //如果緩沖區中剩余的字節大于len,則讀出len長度的字節,如果不夠則讀出剩余的字節數
          // bytesToCopy表示實際讀出的字節數
          int bytesToCopy = bytesInBuffer >= remainder ? remainder : bytesInBuffer;
          byte[] buffer = (byte[])file.buffers.elementAt(bufferNumber);
          System.arraycopy(buffer, bufferOffset, dest, destOffset, bytesToCopy);
          destOffset += bytesToCopy;       //增加已經復制的byte數據長度 到  dest中的偏移量
          start += bytesToCopy;                 //RAMFile文件指針,用來確定bufferNumber 和bytesInBuffer   相當于內存中的分頁
          remainder -= bytesToCopy;       //剩余的還未復制的字節數
        }
        pointer += len;//文件指針位置
      }

    posted @ 2008-04-18 11:45 曉宇 閱讀(224) | 評論 (0)編輯 收藏

    org.apache.lucene.store.RAMOutputStream

    這是OutputStream的一個子類,其輸出設備是內存,準確來說是RAMFile,即將數據寫入到RAMFile的Vector中去。
    該類有一個最重要的方法,現在把它整個貼出來

    public void flushBuffer(byte[] src, int len) {
        int bufferNumber = pointer/BUFFER_SIZE;   //buffer序列,即當前所寫Buffer在RAMFile中的Vector中的序列號
        int bufferOffset = pointer%BUFFER_SIZE;   //偏移量,即當前所寫字節在當前Buffer中的偏移量。
        int bytesInBuffer = BUFFER_SIZE - bufferOffset; //當前Buffer的剩余可寫字節數
       //bytesToCopy是實際寫入的字節數,如果當前Bufer的剩余字節數大于需要寫的字節的總數則寫入所有字節
       //否則,將當前Buffer寫滿即可,剩余的字節將寫入下一個Buffer
        int bytesToCopy = bytesInBuffer >= len ? len : bytesInBuffer;

        if (bufferNumber == file.buffers.size())
          file.buffers.addElement(new byte[BUFFER_SIZE]); //在RAMFile中添加新的byte[1024]元素

        byte[] buffer = (byte[])file.buffers.elementAt(bufferNumber);
        System.arraycopy(src, 0, buffer, bufferOffset, bytesToCopy);

        if (bytesToCopy < len) {     // not all in one buffer,
          int srcOffset = bytesToCopy;
          bytesToCopy = len - bytesToCopy;    // remaining bytes 剩余的未寫入的字節數
          bufferNumber++;                         //將buffer數增加1
          if (bufferNumber == file.buffers.size()) 
            file.buffers.addElement(new byte[BUFFER_SIZE]);
          buffer = (byte[])file.buffers.elementAt(bufferNumber); //剩余字節寫入下一個Buffer
          System.arraycopy(src, srcOffset, buffer, 0, bytesToCopy);
        }
        pointer += len;
        if (pointer > file.length)
          file.length = pointer;        //移位文件指針          在原有的基礎上加上實際寫入的字節總數

        file.lastModified = System.currentTimeMillis(); //修改文件的最后修改時間為當前時間
      }

    從指定的字節數組復制指定長度的字節到RAMFile中去。由于RAMFile中Vector的元素是byte[1024]所以可能存在做一次該操作
    要操作兩個Vector元素的情況。即先將當前byte[1024]數組填滿,再新建一個元素裝載剩余的字節。

    另外還有一個writeTo(OutputStream out)方法,將RAMFile中的數據輸出到另一個輸出流



    posted @ 2008-04-18 11:38 曉宇 閱讀(229) | 評論 (0)編輯 收藏

    org.apache.lucene.store.RAMFile

    這個類比較簡單
    import java.util.Vector;
    class RAMFile {
      Vector buffers = new Vector();
      long length;
      long lastModified = System.currentTimeMillis();
    }

    可以理解為一個存儲在內存中的文件,buffers是存儲數據的容器,length是容器中數據的總的字節數
    lastModified 是最后修改時間。

    在實際使用過程中容器buffers存放的對象是一個byte[1024]數組。

    posted @ 2008-04-18 11:23 曉宇 閱讀(288) | 評論 (0)編輯 收藏

    org.apache.lucene.store.OutputStream

    OutputStream
    這是一個Abstract類,是Lucene自己的一個文件輸出流的基類
    BUFFER_SIZE = 1024  緩沖區 大小為 1024bit
    bufferStart = 0 文件位置指針
    bufferPosition = 0 內存緩沖區指針

     public final void writeByte(byte b) throws IOException {
        if (bufferPosition >= BUFFER_SIZE)
          flush();
        buffer[bufferPosition++] = b;
      }
    幾乎所有的寫入函數都要調用這個函數,如果緩沖區的當前容量已經等于他的最大容量,則將緩沖區中的數據寫入文件。

    public final void writeBytes(byte[] b, int length) throws IOException
    批量寫byte進入內存緩沖

    public final void writeInt(int i) throws IOException
    寫入整形數據

    public final void writeLong(long i) throws IOException
    寫入長整型數據,即結合移位運算調用兩次writeInt(int i)

    另外,最值得注意的是在該類中有兩個最特殊的函數
    writeVInt(int i) /   writeVLong(long i),
    先說
    writeVInt(int  i )   {
     while ((i & ~0x7F) != 0) {                               
          writeByte((byte)((i & 0x7f) | 0x80));
          i >>>= 7;
        }
        writeByte((byte)i);
    }
    ~0x7F==~(0111 1111)==(1000 0000)==0x80
    ((i & ~0x7F) != 0) 這一句判斷i是否大于0x80,如果不是則說明該int只有一個字節的有效數據,其他字節都是0,直接轉化為Byte寫入。
    如果大于0x80則
    (i & 0x7f) | 0x80
    i&0x7f 只對后7位進行處理,|0x80將第8位置1,與前面的7個bit構成一個字節,置1的原因是說明該字節并不是一個完整的整形數,需要與其他的字節合起來才能構成一個整形數字。
    這個算法相當于將一個32bit的整形數字按照每7位編碼成一個字節進行存儲,將按照整形數的大小存儲1-5個字節。

    writeVLong(long i)方法大致與其相同。

    final void writeChars(String s, int start, int length)
    將字符串轉化成UTF-8編碼的格式進行存儲。
    附:

    UNICODE值 UTF-8編碼
    U-00000000 - U-0000007F: 0xxxxxxx
    U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
    U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx

    可見對于在 0x00-0x7F范圍內的UNICODE值(最大有效數位:7位),將會編碼成單字節的,會大大節約存儲空間。
    對于在           0x80-0x7FF范圍內的UNICODE(最大有效數位:11位),會編碼成雙字節的。先存儲原字節低5位的數位,且將最高位和次高位都置1,再次高位置0(writeByte((byte)(0xC0 | (code >> 6)));)。然后存儲后6位的字節,將前兩位置10(writeByte((byte)(0x80 | (code & 0x3F)));)
    對于其他的UNICODE值則
    writeByte((byte)(0xE0 | (code >>> 12)));               4位
     writeByte((byte)(0x80 | ((code >> 6) & 0x3F)));   5位
     writeByte((byte)(0x80 | (code & 0x3F)));            3- 5位

    final void writeString(String s) throws IOException
    該函數首先用s.length()判斷該String總共有多少個字符
    然后首先調用writeVInt寫入這個字符長度
    再調用writeChars(s,s.length())寫入字符


    在inputStream中的readString()方法則與其相反,首先用readVInt()方法讀取字符長度len 然后讀取len長度的字符

    protected final void flush() throws IOException
    該方法調用另外一個方法flushBuffer將緩沖區中的數據輸出,然后清空緩沖區;

    abstract void flushBuffer(byte[] b, int len) throws IOException
    可見flushBuffer方法是abstract的,即需要其子類對該方法進行覆寫,以定位該輸出流的輸出方式。

    final long getFilePointer() throws IOException
    得到文件指針的位置,即得到輸出流已經輸出的字節數。

    public void seek(long pos) throws IOException
    輸出緩沖區的內容,然后將文件指針定位到long所指示的文件位置。

    abstract long length() throws IOException
    返回文件中已有的字節數。需要子類實現。

















    posted @ 2008-04-16 21:24 曉宇 閱讀(218) | 評論 (0)編輯 收藏

    org.apache.lucene.store.FSDirectory

    FSDirectory繼承了abstract類Directory
    在該類中既有該類的一些初始化操作,又有對FSDirectory對象本身的一些操作,這是為什么把其構造函數設置為私有的一部分原因

    static final Hashtable DIRECTORIES = new Hashtable();
    每新建一個FSDirectory都會將其加入到該Hashtable中來。名稱是FSDirectory對應的File   值是該FSDirectory。
    注意:final對象并非是不可更改的

    static final String LOCK_DIR =
        System.getProperty("org.apache.lucene.lockdir",
          System.getProperty("java.io.tmpdir"));
    首先看用戶是否注冊了"org.apache.lucene.lockdir"屬性,如果沒有則用JAVA虛擬機固有的"java.io.tmpdir"屬性
    這個屬性是一個路徑,代表lucene的鎖文件鎖放的位置。

    static final boolean DISABLE_LOCKS =
          Boolean.getBoolean("disableLuceneLocks") || Constants.JAVA_1_1;
    如果用戶注冊了"disableLuceneLocks"屬性且為false,或者JAVA的版本是1.1則無法使用鎖。

    static FSDirectory getDirectory(String path, boolean create)
    static FSDirectory getDirectory(File file, boolean create)
    從得到一個指定路徑或者文件的FSDirectory如果在則取出,如果不存在則用其私有的構造函數構造一個
    該類還有3個非static的類變量
      private File directory = null;      索引目錄
      private int refCount;                   鎖目錄
      private File lockDir;                    索引目錄數目
    實際上,初始化一個FSDirectory只需要初始化這3個變量即可
    如果create的值為true 則:如果索引目錄是已經存在的目錄,則會遍歷該目錄然后刪除每一個文件,如果鎖目錄是已存在的也會用list返回所有的文件然后調用file.delete() 刪除。 如果目錄不存在則創建一個新的。

    注意:list()方法   會先用文件名進行排序然后返回(a.txt會比b.txt先返回)    且delete方法刪除文件夾時,只能刪除空文件夾。如果失敗則跳出程序,不會刪除在該文件夾之后返回的文件。(如果有aa.txt , ab/b.txt , b.txt , 則刪除時候由于a文件夾非空刪除失敗,則b.txt由于前面刪除失敗跳出程序,也不會被刪除,但是aa.txt被正常刪除)

    private FSDirectory(File path, boolean create) throws IOException
    私有的構造函數

    private synchronized void create() throws IOException
    創建新的directory /lockDir目錄,當目錄已存在時即清空該目錄,不存在即創建新的目錄。

    final String[] list() throws IOException
    以字符串文件名的形式返回索引目錄的所有文件

    final boolean fileExists(String name) throws IOException
    在索引目錄是否存在指定文件名的文件

    final long fileModified(String name) throws IOException
    static final long fileModified(File directory, String name)
    返回該文件的最后修改時間,directory參數為相對路徑,第一個函數的相對路徑為索引目錄

    void touchFile(String name) throws IOException
    將該文件的最后修改時間設置為當前時間

    final long fileLength(String name) throws IOException
    返回該文件的長度

    final void deleteFile(String name) throws IOException
    刪除該文件

    final synchronized void renameFile(String from, String to) throws IOException
    重命名該文件
    該方法會首先檢測新的文件名命名的文件是否已經存在如果存在即刪除該文件,然后再將文件重新命名為新的文件名。
    doug cutting在該方法的注釋上寫到:
    1.刪除操作和重命名的操作不是原子的。
    2.重命名操作在有些虛擬機上面不能正確的工作,如果重命名失敗則會采用手動copy的方法。使用輸入輸出流將舊的文件的內容寫入到新的文件中去,然后刪除舊的文件。
    注意:該方法必須是同步的。

    final OutputStream createFile(String name) throws IOException
    用指定的文件名創建一個新的可寫的空文件  實際上返回的是FSOutputStream,注意這里的OutputStream并不是java的基礎類。而是doug cutting自己寫的一個文件隨即訪問類。同理FSInputStream和InputStream也是Lucene自己的類。

    final InputStream openFile(String name) throws IOException
    從一個存在的文件打開一個輸入流

    getLockPrefix()
    在FSDirectory中還有
     private static MessageDigest DIGESTER;這個靜態變量是提供加密功能的
    DIGESTER=MessageDigest.getInstance("MD5"),-----MD5加密算法
    或者可以DIGESTER=MessageDigest.getInstance("SHA"),-----SHA加密算法
    用于對鎖目錄的   文件名的加密
    用法如下:
    digest = DIGESTER.digest(dirName.getBytes());  dirName是需要被加密的字符串,這里是索引文件的目錄名,
    在FSContext中,其應用在 getLockPrefix() 該方法是為某個索引目錄創建其對應的鎖目錄文件名。
    首先返回經過加密后的byte[] 數組digest,然后將digest按照每4個bit轉化為一個16進制的字符,存進一個StringBuffer中
    其轉化類似與Base64編碼方式,不過要簡單得多。

    方法
    Lockl  makeLock(String name)
    是從Directory中擴展而來的,該方法返回一個Lock對象,該對象將會在介紹完Lucene的輸入輸出流之后介紹。
    該方法比較簡單,首先是調用了getLockPrefix() 方法,返回文件鎖的部分對象名,然后在該名稱后面加上鎖的特征名
    譬如說讀寫鎖 事務鎖
    其名稱類似于下:
    lucene-12c90c2c381bc7acbc4846b4ce97593b-write.lock
    lucene-12c90c2c381bc7acbc4846b4ce97593b-commit.lock
    這兩種鎖機制將會在后面介紹
    最后通過一個匿名的內部類返回一個經過重載的Lock對象,該內部類中的方法有鎖的創建,得到,釋放,以及檢測,另外還有一個toString()方法返回鎖的名稱。



    在FSDirectory類中有OutputStream和InputStream的實現類,這兩個虛類只是定義了一些操作,并沒有定義輸入或者輸出的設備。
    Lucene在輸入輸出的設計上,將會由子類定義輸入輸出的設備。
    FSOutputStream
    在FSOutputStream中有一個 RandomAccess File=new RandomAccessFile(path, "rw");
    在對該輸出流的操作將用調用該file的相應方法實現
    最重要的
      public final void flushBuffer(byte[] b, int size) throws IOException {
        file.write(b, 0, size);
      }
    flushBuffer的調用將會將byte中的0--size范圍的數據寫入到文件path中去。


    FSInputStream
    最重要的
    protected final void readInternal(byte[] b, int offset, int len)
           throws IOException {
        synchronized (file) {
          long position = getFilePointer();     //得到該當前文件指針
          if (position != file.position) {
            file.seek(position);
            file.position = position;
          }
          int total = 0;
          do {

       //從文件中讀取指定長度的字節到字節數組
       // 在其基類InputStream中的refill()方法  將會調用  readInternal(buffer, 0, bufferLength);首先從文件中讀取字節到緩沖數組。
      //  在InputStream中每次讀取操作都會調用readInternal方法,或者通過refill()方法間接調用該方法。
            int i = file.read(b, offset+total, len-total);       //將文件中的數據讀到緩沖區
            if (i == -1)
              throw new IOException("read past EOF");
            file.position += i;
            total += i;
          } while (total < len);
        }
      }





















    posted @ 2008-04-10 21:35 曉宇 閱讀(1097) | 評論 (0)編輯 收藏

    org.apache.lucene.document.DateField

    該類提供了日期和字符串之間的相互轉化,實際上是 long型和String型的相互轉化,轉化時用到了一個不常用的
    Long.toString(long,int);方法。是按指定的方式對long型進行轉化
    第一個參數是要轉化的long,第二個參數是轉化時候的基數,如果基數是10就相當于方法Long.toString(long);
    這里使用的參數是最大值,即36== 10個數字+26個英文字母。這樣轉化出來的字符串長度比較短,占用比較少的空間,
    另外,在轉化時,統一了轉化后的字符串長度,如果不足9位(日期的long轉化后最高為9位,1970之后的日期可正確轉換),
    統一長度后的字符串可以通過比較字符串來比較日期的大小。


    日期轉化成的字符串類似于
    0fev8eza3
    本來應該是fev8eza3 采取了不足9位補0的方法。

      private static int DATE_LEN = Long.toString(1000L*365*24*60*60*1000,
                Character.MAX_RADIX).length();
    計算出從1970年開始后1000年的時間轉化為字符串后的長度,所有轉化后的時間都不應超過這個長度,如果不足則在前面補0

    可以通過字符串轉化為日期的函數計算出能表示的最大日期為
    stringToTime("zzzzzzzzz");
    打印出來是 Fri Apr 22 19:04:28 CST 5188  
    所以該函數能轉化的日期范圍為 1970-1-1~~5188-4-22


    日期轉化為字符串
    public static String timeToString(long time)

    字符串轉化為日期
    public static long stringToTime(String s)


    實際上 函數 LongToString(long i,int radix) 相當于  先將i轉化為radix進制的整數,然后再用函數
    LongToString(i)轉化為字符串。所以radix的值應該在2--36之間如果不是 則按照10進制計算。

    posted @ 2008-04-10 19:26 曉宇 閱讀(341) | 評論 (0)編輯 收藏

    org.apache.lucene.document.Document

    Document是一些Field的集合,每個Field有一個名字和文本值,當中的某些Field可能會隨著Documnet被存儲。這樣,每個Document應該至少包含一個可以唯一標示它的被存儲的Field

    //Field集合
    List fields = new Vector();
    //增強因子,作用于該Document的所有Field
    private float boost = 1.0f;
    //向Document中添加Field
    public final void add(Field field) {
        fields.add(field);
      }
    //刪除指定名稱的第一個Field
    public final void removeField(String name)
    //刪除所有擁有指定名稱的Field
    public final void removeFields(String name)
    //得到指定名稱的第一個Field
    public final Field getField(String name)
    //以數組的形式返回指定名稱的所有Field
    public final Field[] getFields(String name)
    //得到所有Field的一個枚舉
    public final Enumeration fields()

    該類也重載了toString()方法
    打印出所有Field的信息




    posted @ 2008-04-08 20:27 曉宇 閱讀(735) | 評論 (0)編輯 收藏

    org.apache.lucene.document.Field類

    package org.apache.lucene.document;   
    Field
    是Document的一部分,每個Field有兩個部分組成 名字-值 對 名字是String 值 可以是String 和 Reader,如果是KeyWord類型的Field,那么值將不會被進一步處理,像URL,Date等等。Field被存儲在Index中,以便于能以Hits的形式返回原有的Document
    Field有3 個Boolean形的標識
      private boolean isStored = false;     被存儲  
      private boolean isIndexed = true;    被索引
      private boolean isTokenized = true  被分割
    通過調整這3個boolean的值,可以確定該Field的類型
      Keyword      true, true, false           一般存儲 URL DATE 等關鍵字
      UnIndexed    true, false, false          一般是隨HITS查詢結果一起返回的信息
      Text              true, true, true           
      UnStored      false, true, true

    另外,還有一個重載的toString方法 可以打印出該Field的類型

    float boost = 1.0f;    增強因子,用于排序的評分,作用于擁有該域(field)的所有文檔(document)

      
     

    posted @ 2008-04-08 20:07 曉宇 閱讀(936) | 評論 (0)編輯 收藏

    僅列出標題
    共4頁: 上一頁 1 2 3 4 下一頁 
    主站蜘蛛池模板: 亚洲麻豆精品果冻传媒| 亚洲精品成人av在线| 亚洲av无码专区在线观看下载 | 国产啪亚洲国产精品无码| 无码天堂va亚洲va在线va| 久久久综合亚洲色一区二区三区| 人与动性xxxxx免费| 亚洲国产精品一区二区九九| 亚洲欧洲日本精品| 99热在线观看免费| 亚洲mv国产精品mv日本mv| 一二三四影视在线看片免费| 亚洲深深色噜噜狠狠网站| 国产一精品一AV一免费| 亚洲AV日韩AV永久无码久久| 色欲色香天天天综合网站免费| 麻豆亚洲AV永久无码精品久久 | 亚洲国产一区视频| 一级特黄录像免费播放肥| 亚洲AV无码一区二区三区DV| 无码专区AAAAAA免费视频| 亚洲成人免费网址| 免费精品一区二区三区在线观看 | 国产精品亚洲AV三区| 国产成人精品日本亚洲专区| a级毛片高清免费视频就| 免费看国产曰批40分钟| 一区二区视频在线免费观看| 亚洲欧洲免费视频| 成人黄页网站免费观看大全| 黄色毛片免费网站| 免费播放特黄特色毛片| 亚洲色无码专区一区| 亚洲AV无码成H人在线观看| 久久久国产精品福利免费| 亚洲成年网站在线观看| 中文字幕不卡亚洲| 免费无码AV片在线观看软件| 免费精品视频在线| 亚洲第一页在线播放| 亚洲国产91精品无码专区|