2012-04-25 28 views
0

我使用下面的代碼從標準的命令行上讀取的SQL語句:有沒有辦法有時需要來自stdin的數據,有時不需要Java?

BufferedReader in = null; 
    StringBuilder sb = new StringBuilder(); 
    String line = null; 
    try { 
     in = new BufferedReader(new InputStreamReader(System.in)); 
     while((line = in.readLine()) != null) { 
      sb.append(line); 
     } 
    } finally { 
     if (in!=null) in.close(); 
    } 

我的問題是,應用程序需要從標準輸入數據有時運行,有時不(無管道輸入) 。如果上述代碼中沒有輸入,則in.readLine()塊。有沒有辦法重寫這段代碼,以便它可以在沒有管道輸入的情況下運行?

更新:該應用程序設計用於期望來自命令行而不是來自鍵盤的管道數據。

+0

Stdin代表控制檯。你怎麼知道用戶是否要輸入或不輸入? – 2012-04-25 17:12:01

+0

感謝彼得 - 更新了這個問題來澄清。 – 2012-05-17 18:18:35

+0

在這種情況下,in.readLine()只會在等待來自文件系統的數據時阻塞。這應該是非常短的(大約10毫秒)我的文件系統非常慢,這似乎阻止了大部分時間,但實際上它正在處理一些數據並重復等待磁盤。 – 2012-05-17 18:23:46

回答

2

我不認爲有任何方法可以檢查您是否最終會獲得另一行輸入。請注意,如果用戶關閉輸入流(例如,在終端中使用^ D),您的當前代碼將終止。

BufferedReader.ready()檢查是否有流上的一些數據。像T.J.上面提到過,你可能不太走運,在你真正收到數據之前要求提供數據,而你的用戶會因爲沒有回答他們的查詢而感到難過。

Scanner.hasNextLine()是阻塞操作,所以可能不是你要找的內容。

你可以讓用戶指定是否通過使用命令行參數,從System.in讀取,例如。

+0

我結束了使用BufferedReader.ready()的完美工作。謝謝! – 2012-05-17 18:19:16

+0

闡述了這一點 - 我發現這隻有當輸入立即可用於'BufferedReader'時才能正常工作。例如,在查詢數據庫的命令行工具中輸入數據時,'ready()'將立即返回false,因爲往返數據庫需要幾ms。相反,我必須按照你的建議編寫一個命令行參數。 – 2012-05-17 19:19:39

2

您可以使用ready測試流是否有數據準備。如果ready返回false,那麼當您調用該流時(它可能在一微秒後收到數據),該流沒有數據準備就緒。如果您撥打ready並返回true,則您知道可以不阻止地撥打read。 (當然,您可能無法撥打readLine

1

支持可選地從stdin讀取的Unix實用程序通常會根據其命令行找出要執行的操作。例如,如果命令行上沒有命名文件,則cat將從標準輸入讀取。你可以沿着這些方向做一些事情 - 添加一個命令行標誌或選項或者其他內容來表明程序是否應該嘗試從stdin中讀取任何內容。

另一種方法是重新從/ dev/null的輸入,如果有你想要的程序來讀取沒有輸入。在這種情況下,您可以從stdin中讀取並立即獲得文件結束指示。相當於從NUL重定向的窗口。

如果你真的需要你的程序能夠檢測它是否可以從標準輸入讀取,而不堵,看InputStream.available()。但是如果你想支持某人在程序的輸入中輸入內容(或者將其粘貼到終端窗口中),那麼在用戶實際輸入內容之前InputStream不會顯示可用輸入。

+0

此外,許多unix utils都支持「特殊」輸入文件「 - 」,意思是「stdin」。 – jtahlborn 2012-04-25 17:11:58

0

這取決於您的程序在沒有管道輸入時的運行方式。通常一個程序會有一個開放的標準輸入,你所能做的就是設置一個定時器,等待一定的時間輸入,如果定時器沒有輸入到期,假設不會有任何輸入。另一種方法是安排程序在標準輸入關閉的情況下運行,在這種情況下,當你嘗試閱讀時你會得到一個EOF。

要關閉標準輸入在UNIX(包括Mac OS),你會寫一個bash腳本啓動程序:

#!/bin/bash 

exec 0>&- # close stdin 

java -jar yourProgram.jar # run your program 

當然,如果你從bash命令行啓動反正,你不「T需要一個腳本:

prompt> java -jar yourProgram.jar 0>&- 

但是如果你的程序是在Java EE容器中運行,我不知道你怎麼會在發射前關閉標準輸入,也許你不能。

0

在unix上,您可以檢查/proc/self/fd/0是否指向文件,管道或控制檯。

$ ls -l /proc/self/fd/0 
lrwx------ 1 peter peter 64 Apr 25 18:12 /proc/self/fd/0 -> /dev/pts/21 
$ ls -l /proc/self/fd/0 < /dev/null 
lr-x------ 1 peter peter 64 Apr 25 18:13 /proc/self/fd/0 -> /dev/null 
$ echo Hello World | ls -l /proc/self/fd/0 
lr-x------ 1 peter peter 64 Apr 25 18:13 /proc/self/fd/0 -> pipe:[139250355] 

這會告訴你輸入是文件,是管道還是終端。

相關問題