天天看點

c語言eof_Java的EOF辨別

這篇是關于JAVA中EOF辨別的講解,之前在工作上碰到過一個問題,有人問過,不能通過判斷EOF來知道檔案有沒有讀取完畢嗎?其實,還真不能。

直接從JDK接口文檔入手,以FileInputStream為例,JDK接口文檔給出了明确的說明:

c語言eof_Java的EOF辨別

使用FileInputStream的read方法讀取檔案時,當傳回-1就表明讀到了檔案末尾,如果期間出現IO異常,則會抛出一個IOException。而對于EOF檔案結束符,其實是不存在的。在Linux系統之中,EOF根本不是一個字元,而是當系統讀取到檔案結尾,所傳回的一個信号值,例如在C語言中,EOF是一個定義在頭檔案stdio.h的常量,一般等于-1。對于JAVA的實作,我們可以通過檢視FileInputStream的源碼檢視,如下:

c語言eof_Java的EOF辨別

其中read0為native方法,需要檢視jvm源碼。根據JVM源碼定位進去,發現read0調用readSingle方法:

c語言eof_Java的EOF辨別

源碼看這FileInputStream.c(http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/5b86f66575b7/src/share/native/java/io/FileInputStream.c)

而readSingle方法位于io_util.c中:

c語言eof_Java的EOF辨別

搓這裡ioutil.c(http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/5b86f66575b7/src/share/native/java/io/io_util.c)跟蹤IO_Read方法,可以得到如下源碼實作:

c語言eof_Java的EOF辨別
c語言eof_Java的EOF辨別

源檔案分别位于ioutilmd.h(http://hg.openjdk.java.net/jdk/jdk/file/bd45ce23b1ac/src/java.base/unix/native/libjava/io_util_md.h)和ioutilmd.c(http://hg.openjdk.java.net/jdk/jdk/file/bd45ce23b1ac/src/java.base/unix/native/libjava/io_util_md.c)

是以,其實read方法最後還是調用了作業系統的read方法,該方法跟具體的作業系統相關,在linux下,有如下的說明

c語言eof_Java的EOF辨別

也就是,當使用read方法去讀檔案時,如果讀到了檔案末尾,沒有字元傳回時,則該方法傳回0,如果出現異常,則傳回-1.然後,JDK在readSingle方法裡進行了包裝,如果傳回0,則在JDK層面傳回-1,如果傳回-1,則抛出IOException.因而,JAVA中沒有EOF這個辨別符,而是使用-1來辨別檔案結束。