Java基礎--FileDescriptor sync方法

百聯達發表於2013-06-08
在讀Lucene的原始碼過程中,發現FSDirectory類中有一個檔案資訊同步的方法,對其中的一行程式碼file.getFD().sync();不是很清楚(這也可見自己的基礎有多麼的差)。經過一番檢索,終於明白了其大意。

  protected void fsync(String name) throws IOException {
    File fullFile = new File(directory, name);
    boolean success = false;
    int retryCount = 0;
    IOException exc = null;
    while (!success && retryCount < 5) {
      retryCount++;
      RandomAccessFile file = null;
      try {
        try {
          file = new RandomAccessFile(fullFile, "rw");
          file.getFD().sync();//強制所有系統緩衝區與基礎裝置同步
          success = true;
        } finally {
          if (file != null)
            file.close();
        }
      } catch (IOException ioe) {
        if (exc == null)
          exc = ioe;
        try {
          // Pause 5 msec
          Thread.sleep(5);
        } catch (InterruptedException ie) {
          throw new ThreadInterruptedException(ie);
        }
      }
    }
    if (!success)
      // Throw original exception
      throw exc;
  }
}
 
FileDescriptor檔案描述符類的例項用作與基礎機器有關的某種結構的不透明控制程式碼,該結構表示開放檔案、開放套接字或者位元組的另一個源或接收者。檔案描述符的主要實際用途是建立一個包含該結構的 FileInputStreamFileOutputStream。 應用程式不應建立自己的檔案描述符。
 
大部分人都認為flush後,其他使用者應該立即可見。但是在一些極端的情況下也需呼叫後還是無法看見以寫入的資料。
 

flush

   重新整理此輸出流並強制寫出所有緩衝的輸出位元組。flush 的常規協定是:如果此輸出流的實現已經緩衝了以前寫入的任何位元組,則呼叫此方法指示應將這些位元組立即寫入它們預期的目標。

   如果此流的預期目標是由基礎作業系統提供的一個抽象(如一個檔案),則重新整理此流只能保證將以前寫入到流的位元組傳遞給作業系統進行寫入,但不保證能將這些位元組實際寫入到物理裝置(如磁碟驅動器)。

 OutputStreamflush 方法不執行任何操作。為什麼會這樣? 原因是,這個緩衝我們java自己實現的。 flush保證的是內部的緩衝寫入到系統中。但是系統中檔案也可能有緩衝,所以並不一定flush後立即可見。

 那麼如何解決這個問題?在檔案流或資料流中均可以看見getFD()這個方法, 它返回的是與此流有關的檔案描述符。

所以呼叫檔案描述符的sync的方法即可讓實際檔案強制同步了。JDK中描述如下:

sync

強制所有系統緩衝區與基礎裝置同步。該方法在此 FileDescriptor 的所有修改資料和屬性都寫入相關裝置後返回。特別是,如果此 FileDescriptor 引用物理儲存介質,比如檔案系統中的檔案,則一直要等到將與此 FileDesecriptor 有關的緩衝區的所有記憶體中修改副本寫入物理介質中,sync 方法才會返回。 sync 方法由要求物理儲存(比例檔案)處於某種已知狀態下的程式碼使用。例如,提供簡單事務處理設施的類可以使用 sync 來確保某個檔案所有由給定事務造成的更改都記錄在儲存介質上。 sync 隻影響此 FileDescriptor 的緩衝區下游。如果正透過應用程式(例如,透過一個 BufferedOutputStream 物件)實現記憶體緩衝,那麼必須在資料受 sync 影響之前將這些緩衝區重新整理,並轉到 FileDescriptor 中(例如,透過呼叫 OutputStream.flush)。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28624388/viewspace-763524/,如需轉載,請註明出處,否則將追究法律責任。

相關文章