這篇是關於JAVA中EOF標識的講解,之前在工作上碰到過一個問題,有人問過,不能通過判斷EOF來知道文件有沒有讀取完畢嗎?其實,還真不能。
直接從JDK接口文檔入手,以FileInputStream為例,JDK接口文檔給出了明確的說明:

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

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

源碼看這FileInputStream.c(http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/5b86f66575b7/src/share/native/java/io/FileInputStream.c)
而readSingle方法位於io_util.c中:

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


源文件分別位於io_util_md.h(http://hg.openjdk.java.net/jdk/jdk/file/bd45ce23b1ac/src/java.base/unix/native/libjava/io_util_md.h)和io_util_md.c(http://hg.openjdk.java.net/jdk/jdk/file/bd45ce23b1ac/src/java.base/unix/native/libjava/io_util_md.c)
所以,其實read方法最后還是調用了操作系統的read方法,該方法跟具體的操作系統相關,在linux下,有如下的說明

也就是,當使用read方法去讀文件時,如果讀到了文件末尾,沒有字符返回時,則該方法返回0,如果出現異常,則返回-1.然后,JDK在readSingle方法里進行了包裝,如果返回0,則在JDK層面返回-1,如果返回-1,則拋出IOException.因而,JAVA中沒有EOF這個標識符,而是使用-1來標識文件結束。

個人公眾號:啊駝
