Java之IO(六)FileInputStream和FileOutputStream


  轉載請注明源出處:http://www.cnblogs.com/lighten/p/7001458.html

1.前言

  前五章按照JDK的類順序介紹了幾種流,第五章講了Java的文件系統。本章介紹Java的第一個真正意義的流源頭:文件流。之前介紹的都是一些流的裝飾類,主要作用是更好的處理流的內容,比如緩存,讀取內容等。ByteArray流可以說是一個偽源,其接受一個字節數組作為數據源。毫無疑問文件流涉及操作系統的文件,肯定是通過native方法進行讀取。下面對其有些什么操作進行介紹。

2.FileInputStream

  FileInputStream是真正的輸入源,不同於其它流,所以其不繼承FilterInputStream,而是直接繼承抽象父類InputStream。其構造函數如下:

  接收一個文件路徑,或者是一個File實例,或者是一個FileDescriptor實例。這個類的介紹看第四小節。

  所有覆寫抽象類的方法最終調用的都是native方法,所以也沒有什么好說明的。唯一值得說明的就是close方法,其不止調用了native的close方法,還關閉了所有具有相同FileDescriptor實例的流。

3.FileOutputStream

  FileOutputStream的構造方法和輸入流的差不多,但是區別在於多了一個boolean參數,也就是是否是追加模式。了解C語言的都知道,文件寫入默認情況下都會丟棄之前文件中的內容,但是對文件也有追加的模式,就是在原內容最后繼續寫。Java也就是實現了相同的功能,默認也是false,即不追加,覆蓋原文件內容。

  除了這一點,其它的也和FileInputStream的情況一樣,覆寫父類的方法都是調用了native方法,沒有什么好講的地方。

4 相關類介紹

4.1 FileDescriptor

  該類的實例被看作成一個不透明的句柄,句柄指向一個底層的機器特定的結構,可能表示一個打開的文件,一個打開的socket套接字,一個其它源或者是一些字節。主要實際的作用是用來創建一個FileInputStream或FileOutputStream實例並持有它。這個類結構比較簡單,只有一個空參的構造函數,但是理解起來不太容易。先看一個例子再來理解其使用方法。

    @Test
	public void test() throws IOException {
		FileDescriptor descriptor = new FileDescriptor();
		FileInputStream fis = new FileInputStream(descriptor);
		try {
			System.out.println(fis.read());
		} catch (IOException e) {
			System.out.println("fis執行異常");
		} 
		String path = FileDescriptorTest.class.getClassLoader().getResource("").getPath()+"test.txt";
		File file = new File(path);
		fis = new FileInputStream(file);
		descriptor = fis.getFD();
		FileInputStream nfis = new FileInputStream(descriptor);
		System.out.println("nfis>>>"+nfis.read());
		FileInputStream sfis = new FileInputStream(descriptor);
		System.out.println("sfis>>>"+sfis.read());
		System.out.println("nfis>>>"+nfis.read());
		nfis.close();
		try {
			System.out.println("sfis>>>"+sfis.read());
		} catch(Exception e) {
			System.out.println("nfis執行異常");
		}
		sfis.close();
		fis.close();
	}

  運行結果是:

  這個例子可以看出幾點:1.直接new創建的FileDescriptor實例,生成的流是無效流。2.通過一個有效流獲取的FileDescriptor可以用作生成一個新的流。3.所有共用相同FileDescriptor實例的流,其操作是相互影響的,比如A流讀了一個字節,B流再讀是讀取下一個字節,如果A流關閉了,B流也會關閉。這個就是FileDescriptor的作用,其是一個句柄,可以被很多個流實例共享,但是操作是相互影響的。

  代碼的邏輯很簡單,但是看不出相互關聯。網上找了一下,大致的意思是這個類是一個文件描述符或者說是一個句柄。按照我個人的理解就是這個類其實對應着硬件的一個資源,我們所創建的文件流其實只是一個Java實例,其與一個文件句柄相關聯。如果不同的流有同一個文件句柄,那么操作就會互相干擾。至於文件句柄對應一個文件,負責真正的文件資源,打開,讀取,寫入,關閉,不在意是哪個流實例操作的,但是這個會對其它持有相同句柄的Java流產生影響,這個觀點可能有所錯誤,如有清楚的,請指教一下。Java代碼中流並沒有對這個實例進行操作,只是調用native方法,也就調用attch方法與具體的流實例相互關聯了,這個操作是不是JVM管理的不甚清楚。

  


免責聲明!

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



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