JAVA I/O操作那些事之标准I/0
? ? ? ?java 提供的標(biāo)準(zhǔn)模型有 System.in, System.out, System.err。平日里我們經(jīng)常用到他們3個(gè),其中用的最多的就是System.out.println()等了,最近突然想到,他們是怎么實(shí)現(xiàn)的呢?
下面是JDK中者三者的定義的源碼:
public final static InputStream in = nullInputStream();public final static PrintStream out = nullPrintStream();public final static PrintStream err = nullPrintStream();? ? ? ? 從上面的代碼上我們可以用到,除了in,其他兩者都已經(jīng)封裝成了PrintStream格式,我們可以直接使用他們。而in則有點(diǎn)特殊,它只是一個(gè)沒有被包裝過的未經(jīng)加工的InputStream(這是Thinking in java的原話,但是在實(shí)際我發(fā)現(xiàn),這個(gè)InputStream的真實(shí)類型應(yīng)該是BufferedInputStream,有可能是我對這句話的理解有誤導(dǎo)致的吧),鄙人在學(xué)C++的時(shí)候,依稀記得,當(dāng)出現(xiàn)cin>>這樣的標(biāo)識的時(shí)候,程序會停下來等待鍵盤的輸入操作,但是在Java中用起來要費(fèi)勁些,直接這么簡單粗暴的輸入,是沒有效果的。一般情況下,我們需要對其進(jìn)行包裝,下面的例子就是其中的一個(gè)方法
InputStream in = System.in;BufferedReader stdin = new BufferedReader(new InputStreamReader(in));//對其進(jìn)行包裝System.out.print("請輸入字符: "); String str = stdin.readLine();//等待鍵盤輸入,按回車結(jié)束System.out.println("你輸入的字符為: " + str);? ?回到開篇講到的內(nèi)容,我們注意到in,out返回的是方法?nullInputStream()、nullPrintStream()方法執(zhí)行后的結(jié)果,我第一次看的時(shí)候,想當(dāng)然就以為這兩個(gè)方法返回的是inputStream、和PrintStream。后來走到源碼中一看,才傻眼了,這兩個(gè)方法是這樣的
/*** The following two methods exist because in, out, and err must be* initialized to null. The compiler, however, cannot be permitted to* inline access to them, since they are later set to more sensible values* by initializeSystemClass().*/private static InputStream nullInputStream() throws NullPointerException {if (currentTimeMillis() > 0) { //一般情況下,不會出現(xiàn)<=0的情況return null;}throw new NullPointerException();}private static PrintStream nullPrintStream() throws NullPointerException {if (currentTimeMillis() > 0) {return null;}throw new NullPointerException();}從上段代碼中我們可以看到,其實(shí)這兩個(gè)方法返回的是null(或者是出現(xiàn)一個(gè)運(yùn)行時(shí)的異常)。那么問題來了,竟然是null值,那它們是如何操作與初始化的。
?好在,方法之前有一大段的注釋,說明這連個(gè)方法之所以存在時(shí)應(yīng)為in,out等必須初始化為空(why?等待高手解答啊。。。),那么何時(shí)才是真正的執(zhí)行初始化操作呢?
答案就在initializeSystemClass()這個(gè)方法里
? ? ? ? ? ?
/*** Initialize the system class. Called after thread initialization.*/private static void initializeSystemClass() {props = new Properties();initProperties(props);sun.misc.Version.init();// Load the zip library now in order to keep java.util.zip.ZipFile// from trying to use itself to load this library later.loadLibrary("zip");FileInputStream fdIn = new FileInputStream(FileDescriptor.in);FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);setIn0(new BufferedInputStream(fdIn));setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true)); /** * 以上只是部分代碼,下面是無關(guān)的代碼,略去 */在上面這段代碼里,setIn0等方法的代碼如下
private static native void setIn0(InputStream in);private static native void setOut0(PrintStream out);private static native void setErr0(PrintStream err);可以看到上面這三個(gè)方法都是native方法,那么我們就不能繼續(xù)跟下去了,但是我們可以看setIn,setOut,setErr方法,我們知道,這三個(gè)方法用于沖定向標(biāo)準(zhǔn)的I/O流。
public static void setIn(InputStream in) {checkIO(); //用于權(quán)限的檢查setIn0(in);}public static void setOut(PrintStream out) {checkIO();setOut0(out);}public static void setErr(PrintStream err) {checkIO();setErr0(err);}這三個(gè)方法都調(diào)用了相應(yīng)的setXX0()方法,由此我們可以推出setIn0等方法用于重定向輸入輸出流。
? ? 那么重定位到哪呢? ?答案就是
new FileInputStream(FileDescriptor.in) new FileOutputStream(FileDescriptor.out) new FileOutputStream(FileDescriptor.err)public static final FileDescriptor in = standardStream(0);public static final FileDescriptor out = standardStream(1);public static final FileDescriptor err = standardStream(2);
/**
* 返回handle為fd的FileDescriptor; 在傳統(tǒng)的unix的系統(tǒng)中,fd為0,1,2分別表示為標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出和錯(cuò)誤輸出。
*/private static FileDescriptor standardStream(int fd) {FileDescriptor desc = new FileDescriptor();desc.handle = set(fd);return desc;} 所以 setIn0(new BufferedInputStream(fdIn)); 就是將標(biāo)準(zhǔn)輸入先封裝成文件輸入流(FileInputstream),再封裝成BufferedInputStream(典型的裝飾模式啊) 差不多這些了,大致過程都清楚了,但是仍有一些細(xì)節(jié)后續(xù)需要繼續(xù)弄明白,如:為什么初始化必須為空,什么時(shí)候調(diào)用的initializeSystemClass()方法。 ?
?
?
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/chenfei0801/archive/2013/03/28/2987899.html
總結(jié)
以上是生活随笔為你收集整理的JAVA I/O操作那些事之标准I/0的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BA(free scale) netwo
- 下一篇: 开机怎么进入同方安装 同方安装如何进入开