感謝大佬:https://blog.csdn.net/u012345283/article/details/39027745
大家先來看如下這個程序
public class TestInputStream {
public static void main(String args[]) throws IOException {
InputStream in = System.in;
int a = in.read();
System.out.println(a);
a = in.read();
System.out.println(a);
a = in.read();
System.out.println(a);
}
}
大家先來看如下這個程序
問題一:如果輸入”a“,那么會輸出什么呢?事實上我輸入“a”,它並沒有反應
問題二:如果輸入“a”並按下了回車,那么會輸出什么呢?
97 13 10,並且程序結束運行
問題三:如果只按下回車,那么會輸出什么呢?
13 10,並且程序未結束運行
問題四:如果輸出“abc”,那么會輸出什么呢?
97 98 99
好了,例子將完了,下面來分析下上面4種情況
首先我們需要知道System.in到底是什么?
直接輸出System.in我們可以發現它是一個BufferedInputStream
那么BufferedInputStream.read()是如何運作的?
我們可以粗略的掃一下源碼
private void fill() throws IOException {
byte[] buffer = getBufIfOpen();
if (markpos < 0)
pos = 0; /* no mark: throw away the buffer */
else if (pos >= buffer.length){ /* no room left in buffer */
// 這里是設置了mark之后的操作,不需要關心
}
count = pos;
int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
if (n > 0)
count = n + pos;
}
其中buffer是BufferedInputStream的緩沖區,read(byte[] b, int off, int len)方法是從底層輸入流讀取數據,該方法為阻塞方法,那么什么時候會返回呢?
調試進去發現,System.in中底層輸入流為FileInputStream,根據官方文檔上的描述:
1、如果 len 不為 0,則在輸入可用之前,該方法將阻塞
2、返回讀入緩沖區的字節總數,如果因為已經到達文件末尾而沒有更多的數據,則返回 -1。
那么對於控制台輸入該如何判斷達到“文件末尾”呢?通過回車來提交數據,並告訴程序提交完畢。
下面針對上面的問題一一解答
1、由於在控制台輸入時,按下回車鍵才代表輸入完成,輸入的內容才會提交到read()方法,所以按下回車之前,程序是不知道你輸入了什么的
2、輸入"a"后按下回車,這時候read()方法讀到了數據,此時buffer中的數據應該是97 13 10,也就是字符'a','\r', '\n',並且read()方法每次只能從緩沖區中讀出一個字符,三次read()就剛好讀出這3個字符,之后程序就結束了。
3、只按下回車,此時從流中只讀到了"\r"和"\n",由於沒有足夠的輸入,那么第三次調用read()時阻塞
4、輸入"abc",此時從流中讀到"a","b","c","\r","\n",由於只read()了3次,那么讀出abc,\r和\n仍在buffer中
補充:

