FileChannel閱讀筆記

FileChannel閱讀筆記

一、簡介

​ 主要作用是讀取、寫入、映射和操作文件的通道。該通道永遠是阻塞的操作,內部維護了一個當前文件的position。該文件本身包含一個可讀寫、長度可變的字節序列,並且可以查詢該文件的當前大小。

二、繼承關係圖

在這裏插入圖片描述

  • ByteChannel:具有可讀寫字節的通道(繼承的WriteableChannel和ReadByteChannel)
  • SeekableByteChannal:可以維護通道的position和允許position發生改變
  • AbstractInterruptibleChannel:提供一個可被中斷的通道

三、存儲結構

四、源碼分析

內部類

  • MapMode 就是用於映射文件採用什麼模型,讀、讀寫、專用三種

屬性

  • 字段不用介紹了

構造

  • 就一個受保護的無參構造器

主要方法

1、write方法

具有同步,遵循mark、position、limit、capacity

  • public abstract int write(ByteBuffer src) throws IOException;
    • 寫操作,將remaining字節從給定的緩衝區寫入此通道的當前位置。
  • public abstract long write(ByteBuffer[] srcs, int offset, int length)throws IOException;
    • 批量部分寫操作,以指定緩衝區數組的offset下標開始,向後使用length個字節緩衝區,再將每個緩衝區的remaining剩餘字節子序列寫入此通道的當前位置
  • public final long write(ByteBuffer[] srcs) throws IOException
    • 批量寫操作,將每個緩衝區的remaining字節序列寫入到此通道的當前位置,調用的就是上面的方法。
  • public abstract int write(ByteBuffer src, long position) throws IOException;
    • 向通道的指定位置寫入數據,將緩衝區的remaining剩餘字節序列寫入到通道的指定位置。此操作不用影響通道原有的position值。
2、read方法

具有同步,遵循mark、position、limit、capacity

讀取返回結果就是本次讀取的字節數量。如果是 -1 說明沒有數據讀取出來

  • public abstract int read(ByteBuffer dst) throws IOException;
    • 寫操作,將字節序列從此通道的當前位置讀入給定的緩衝區的當前位置。
  • public abstract long read(ByteBuffer[] dsts, int offset, int length)throws IOException;
    • 批量部分讀操作,將通道當前位置的字節序列讀入以數組下標爲offset開始的ByteBuffer[]數組中的remaining剩餘空間中,並且連續寫入length個ByteBuffer緩衝區。
  • public final long read(ByteBuffer[] dsts) throws IOException
    • 批量讀操作,將字節序列從此通道讀入給定的緩衝區數組中的第0個緩衝區的當前位置
  • public abstract int read(ByteBuffer dst, long position) throws IOException;
    • 讀取通道指定位置的數據將通道指定位置的字節序列讀入給定的緩衝區的當前位置。
3、position方法
  • public abstract FileChannel position(long newPosition) throws IOException;
    • 設置此通道的文件位置
    • 將該位置設置爲大於文件當前大小的值是合法的,但這不會更改文件大小,
      • 稍後試圖在這樣的位置讀取字節序列將返回已到達文件末尾的指示(-1)
      • 稍後試圖在這樣的位置寫入字節序列將導致文件擴大,以容納新的字節,在以前文件末尾和新寫入字節之間的字節值是未指定的。
4、truncate方法
  • public abstract FileChannel truncate(long size) throws IOException;
    • 將此通道的文件截取爲給定大小
      • 如果給定大小小於該文件的當前大小,則截取該文件,丟棄未見新末尾後面的所有字節。
      • 如果給定大小大於或等於該文件的當前大小,則不修改文件。
      • 無論是哪種情況,如果此通道的文件位置大於給定大小,則將位置設置爲該大小。
5、transferTo方法
  • public abstract long transferTo(long position, long count,WritableByteChannel target)throws IOException;
    • 將數據傳輸到其他可寫入字節通道
    • 其實和write一樣,只不過是將通道中的數據傳輸到另一個通道中,而不是緩衝區中
      • 從自己通道指定的position開始讀取count個字節,寫入到指定的target字節通道的當前位置
      • 如果給定的位置大於該文件的當前大小,則不傳輸任何字節。
      • 如果count大於position到size的字節個數則會只傳輸sizie-positin個字節
6、tranferForm方法
  • public abstract long transferFrom(ReadableByteChannel src,long position, long count)throws IOException;
    • 將字節從給定可讀取字節通道傳輸到此通道的文件中
      • 此方法不會修改通道的position
      • src 源通道
      • position 從自己的position開始接受src讀取出來的數據
      • count 要接受的最大字節數,
7、lock方法
  • public abstract FileLock lock(long position, long size, boolean shared)throws IOException;
    • 獲取此通道的文件給定區域的鎖定
      • 會阻塞
      • 在鎖定該區域之前、已關閉此通道之前或者已中斷調用線程之前(以先到者爲準),將紫塞此方法的調用
      • 在此方法調用期間,如果另一個 線程關閉了此通道,則拋出AsynchronousCloseException異常
      • 文件的擴大和縮小不會影響鎖定的範圍
        • position鎖定的開始位置
        • size 鎖定的大小
        • shared true爲共享鎖,false爲獨佔鎖
          • 共享鎖,自己能讀,不能寫,別人能讀、不能寫
          • 獨佔鎖,自己能讀、能寫,別人不能讀、不能寫
  • public final FileLock lock() throws IOException
    • return lock(0L, Long.MAX_VALUE, false);內部就是調用的上面,用的Long.MAX_VALUE
    • 所以不做說明。就是開啓了獨佔鎖從0開始到Long.MAX_VALUE的最大值
8、tryLock方法
  • public abstract FileLock tryLock(long position, long size, boolean shared)throws IOException;
    • 獲取通道文件給定區域的鎖定
      • 不會阻塞
      • 如果由於其他程序保持着一個重疊鎖定而無法獲取鎖,返回null
      • 如果由於任何其他原因無法獲取鎖定,則拋出相應的異常
      • 某些操作系統不支持共享鎖定,在這種情況下,自動將對共享鎖定的請求轉換爲對獨佔鎖定的請求,可以通過調用鎖定對象的siShard()的方法來測試獲新獲取的鎖定是共享鎖還是獨佔鎖
  • public final FileLock tryLock() throws IOException
    • return tryLock(0L, Long.MAX_VALUE, false);內部就是調用的上面,用的Long.MAX_VALUE
    • 所以不做說明,就是嘗試用獨佔鎖從0開始到Long.MAX_VALUE的最大值鎖定
9、force方法
  • public abstract void force(boolean metaData) throws IOException;
    • 強制將所有對通道文件的更新寫入包含文件的存儲設備
      • 操作系統爲了運行的效率,先是把那些將要保存到硬盤上的數據暫時放入操作系統內核的緩衝區,以減少硬盤的讀寫次數,然後再某一個時間點再將內核緩存中的數據批量同步到硬盤中,但是同步的時間卻是由操作系統決定的,因爲時間是未知的,這時就不能讓操作系統來決定,所以要顯式的調用force(boolean)方法來強制執行同步
      • 執行force方法是有運行效率成本的。
10、map方法
  • public abstract MappedByteBuffer map(MapMode mode,long position, long size)throws IOException;
    • 將通道文件區域直接映射到內存
      • FileChannel.MapMode.PRIVATE
        • 專用:對於得到的緩衝區的更改不會傳播到文件,並且該更改對映射到同以文件的其他程序是不可見的。但是會創建緩衝區已修改部分的專用副本。
      • FileChannel.MapMode.READ_ONLY
        • 只讀,試圖修改得到的緩衝區將拋出ReadOnlyBufferException異常
      • FileChannel.MapMode.READ_WRITE
        • 讀取/寫入:對得到的緩衝區修更改最終將傳播到文件;
          • 但是該更改對映射到同一個文件的其他程序不一定是可見的。
      • position和size 就是映射的區域
11、open
  • StandardOpenOption 用於打開指令

    • READ	讀,	打開以進行讀取訪問
      WRITE	寫,
      APPEND	追加,	如果打開文件以進行寫入訪問,則字節將寫入文件末尾而不是開始
      TRUNCATE_EXISTING	如果該文件已存在並且爲寫入訪問而打開,則其長度將被截斷爲0.
          			   如果文件爲讀取訪問打開,則忽略
          			   也就是用這樣的方式打開後關閉,會清空文件
      CREATE	創建,	單獨使用CREATE常量不可以創建,需要結合WRITE
      CREATE_NEW	創建新的,	如果該文件存在,則失敗拋異常,如果結合WRITE則不會拋異常
      DELETE_ON_CLOSE	關閉時刪除
      SPARSE	稀疏文件,	與CREATE_NEW選項一起使用時,此選項提供了一個提示,
      				   表明新文件講是稀疏的。當文件系統不支持創建稀疏文件時,將忽略該選項。
      	因爲,其他指令,也就是如果opsition是10000 處寫入了a,那麼就會佔用10000的空間,
      	但是用SPARSE可以達到只佔用a,這樣可以有效利用空間
      	注意:不要使用CREATE來創建SPARSE文件,而是使用CREATE_NEW來創建稀疏文件
      SYNC	同步,	要求對“文件內容或元數據”的每次更新都同步寫入底層存儲設備。這樣做,程序效率降低
      SYNC	同步,	要求對“文件內容”的每次更新都同步寫入底層存儲設備
      
12、isOpen
  • 判斷通道是否打開,打開返回true,沒有返回false。

補充

1、FileLock類的API
  • isShard() 如果返回true是共享鎖,返回false是獨佔鎖
  • overlaps() 測試鎖定範圍是否與 現有鎖定重疊,需要傳入測試區域 position和size
  • release() 釋放鎖
  • channel() 返回當前鎖所屬的FileChannel文件通道對象
  • acquireBy() 返回當前鎖所屬的FileChannel文件通道對象,最新的jdk中用於替代channel函數
2、MappedByteBuffer類
  • 它是直接字節緩衝區,其內容是文件的內存映射區域,映射的字節緩衝區是通過FileChannel.map()方法創建的。此類用於特定於內存映射文件區域的操作擴展ByteBuffer類,這個映射關係會一直保持到該緩衝區本身成爲垃圾之前
    • force():將此緩衝區所做的內容更改強制寫入包含映射文件的存儲設備中,會影響效率
    • isLoaded():判斷此緩衝區的內容是否位於物理內存中
      • 如果是true,說明是位於物理內存中,因此是可訪問的,不會導致任何虛擬內存頁錯誤
    • load():將此緩衝區的內容加載到物理內存中
      • 調用此方法可能 導致一些有頁面錯誤,並導致發生I/O操作

五、總結

太懶了, 沒什麼總結的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章