當應用程序請求打開或操作文件時,操作系統會為該應用程序提供一個文件列表,并分配一個非負整數作為索引號。這個索引號就像地址或指針,用于在內存中定位文件數據。在類unix系統中,這個索引號被稱為文件描述符,而在windows系統中則被稱為句柄,用于標識各種對象。
文件描述符是類unix系統中用于描述任何資源對象的概念,類似于Java中的class對象。在Java中,文件描述符的概念通過java.io.FileDescriptor類來抽象。對于FileInputStream、FileOutputStream和RandomaccessFile,使用handle來表示底層的文件句柄;而對于ServerSocket和Socket,則使用fd來表示底層的文件句柄。文件描述符的無效值為-1。
文件描述符類的實例用作與基礎機器相關的某種結構的不透明句柄,用于表示打開的文件、套接字或其他字節源或接收者。主要用于創建包含該結構的FileInputStream或FileOutputStream。應用程序不應自行創建文件描述符,因為它們是由操作系統提供的。
文件描述符就像電話號碼,通過它可以定位到具體的文件或資源,但它本身并不是文件或資源。應用程序在需要服務時,將文件描述符傳遞給操作系統,由操作系統處理具體操作。文件描述符是操作系統管理和維護的抽象概念,應用程序通過請求操作系統來進行文件操作。
在Java中,FileDescriptor類內置了三個文件描述符,分別是標準輸入(in)、標準輸出(out)和標準錯誤(err)。它們的具體值分別是0、1和2,這些值是操作系統層面的描述。在Linux中,每個進程啟動時會打開這三個文件。
文件描述符通常不直接使用,而是通過System.in、System.out和System.err來訪問。這些標準輸入輸出是共享的,但在Java的多線程環境中需要特別處理。在系統初始化之前,線程不能使用這些對象。System類在加載時會將它們初始化為null,之后通過initializeSystemClass方法進行初始化。
initializeSystemClass方法使用這三個文件描述符創建FileInputStream和FileOutputStream對象。對于out和err,根據編碼轉換為PrintStream,然后通過本地方法進行設置。因此,應用程序不直接創建文件描述符,而是通過系統調用和本地方法來操作和使用它們。