FileChannel的深入理解


一,官方描寫敘述


    一個讀,寫,映射,操作文件的通道。

    文件通道有能夠被查詢和改動的一個當前位置。文件本身包括了一個可悲讀寫的變長字節序列,而且它的當前的size會被查詢。當被寫入的字節超過當前文件的大
小時。文件的大小會添加;當文件被截斷的時候,文件的大小會降低。文件有一個寫被關聯的像權限,內容類型和最后改動時間的元數據;這個類未定義訪問元數
據的方法。

    此外對於熟悉的字節通道讀寫關閉操作,這個類定義了下面的特定文件操作:

    1.在文件的絕對位置的字節讀寫操作在某種程度上不會影響通道的當前位置。

    2.文件的區域可能會被直接映射到內存中,對於大文件來說。這比通常的讀寫方法更有效。

    3.為了保證數據在系統崩潰之后不丟失數據。文件的改動模式會被強制究竟層存儲設備。

    4.字節能從一個文件被轉換為一些其它的通道,反之亦然。這樣的操作在某種程度上會被很多操作系統或者文件系統優化成一個很高速的直接傳輸。

    5.文件的區域或許會被鎖住來防止其他程序的訪問。

   

文件通道在多線程下是安全的,close方法能在不論什么時候被調用,這種方法在接口Channel中被指定。在不論什么時間。僅僅有涉及到通道的position
和改變它的文件的size的過程中的操作。當第一個這個方案在處理中時嘗試初始化第二個這種操作將被堵塞,知道第一個操作完畢。

其他的操作,特別是顯
式的獲取position,會被同步處理;它們是否其實做了同步,這樣以來於底層操作系統的實現,因此是未特別指定的。

    文件的視圖通過這個類的實例被提供。這個視圖確保跟在同樣程序中的被其他實例提供的同樣文件視圖的一致性。這個類的實例或許會或許不會提供視圖,通過其他的
同步程序保持視圖的可見性。應歸於被執行的底層操作系統和網絡文件系統延遲的引導的緩存。

無論語言在其他程序中寫,這是事實。並且無論它們執行在同樣的機
器上還是不同的機器上,不論什么這種不一致的確切性質是依賴於系統,因此,未特指。

    這個類未定義打開文件或者創建一個新文件的方法;這些方法或許在未來的發行版中被加入。

像這種文件通道能夠通過
FileInputStream,FileOutputStream,RandomAccessFile類中的getChannel方法獲得。這個
getChannel返回的文件通道是被連接到同樣的底層文件的。

    文件通道的狀態與通過getChannel方法返回的channel對象是緊密相連的,假設明白的改變文件通道的position或者讀寫字節,則會改變原
始對象的文件position,反之亦然。通過文件通道改變文件通道的長度將改變原始對象的文件長度,反之亦然。改變文件通道的內容也會改變原始對象的文
件內容,反之亦然。

    這個類指定了個別的指針。像“僅僅讀打開”,“僅僅寫打開”。“讀寫打開”。通過FileInputStream的getChannel方法獲取的文件通道是僅僅
讀的。當然通過FileOutputStream的getChannel的方法獲取的文件通道是可寫的。通過RandomAccessFile的
getChannel的方法獲取的文件通道。在創建時假設傳遞的參數是“r",則為僅僅讀,否則為”讀寫“或者“寫”。

    文件通道或許在追加模式下被打開,
比如它的獲得是通過一個給FileOutputStream(boolean)或者FileOutputStream(FIle,boolean)傳遞參
數true時,則這個通道是在追加模式下。在這樣的模式下。每一個相對寫方法的調用操作首先會把position增長到文件尾部。然后寫入被請求的數據。

是否
文件position的增長和數據的寫入在原子操作下被完畢是依賴於操作系統的。並為特指。


二,源代碼分析


FileChannel這個類是繼承於抽象類AbstractInterruptibleChannel,實現了接口ByteChannel,GatheringByteChannel,ScatteringByteChannel。

因為這個類的實現類FileChannelImpl沒有被提供源代碼。因此。在JDK中是看不到的,想看源代碼,猛擊這里FileChannelImpl

至於源代碼分析,博主看了幾個小時也沒看出個門道來,太復雜。並且又接近底層,博主如今還沒能力分析源代碼,所以就不分析了。有志向一探到底的,大家能夠自己去看看啊。

三,實例


package test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class FileChannelTest {
    private static final String outputPath = "output.txt";
    private static String data = "你好,我是張三
我今天非常開心和你約會
請多多不吝賜教";
    public static void main(String[] args) throws IOException {
        File inputFile = new File(outputPath);
        File outputFile = new File(outputPath);
        if(!inputFile.exists()) {
            inputFile.createNewFile();
        }
        if(!outputFile.exists()) {
            outputFile.createNewFile();
        }
        //實例化輸入輸出流,而且獲取相相應的FileChannel實例
        FileInputStream fis = new FileInputStream(inputFile);
        FileChannel inputChannel = fis.getChannel();
        FileOutputStream fos = new FileOutputStream(outputFile);
        FileChannel outputChannel = fos.getChannel();
        //獲取數據的字節數組
        byte[] outputBuffer = data.getBytes();
        //分配一個字節緩沖(這個類在下一篇中介紹)
        ByteBuffer obb = ByteBuffer.allocate(1024);
        //將字節數組讀入字節緩沖中
        obb.put(outputBuffer);
        obb.flip();  //調用該方法表示開始讀取字節緩沖中的數據。即limit=position,position=0
        //將字節寫入文件里
        int n = outputChannel.write(obb);
        outputChannel.close();  //關閉通道
        System.out.println("output n is " + n);
        fos.close();  //關閉輸出流
        //再分配一個字節緩沖
        ByteBuffer ibb = ByteBuffer.allocate(1024);
        //將數據從通道中讀入字節緩沖中
        int in = inputChannel.read(ibb);
        //初始化一個字節數組。這個字節數組的長度不能大於這個字節緩沖的limit-position的長度,不然會拋出java.nio.BufferUnderflowException
        byte[] inputBuffer = new byte[ibb.position()];
        //准備從字節緩沖中讀取數據
        ibb.flip();
        System.out.println("input n is " + in);
        //將數據讀入字節數組中
        ibb.get(inputBuffer);
        System.out.println(new String(inputBuffer));
        inputChannel.close();
        fis.close();
    }

}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM