Java 字元終端上獲取輸入 System.in
阿新 • • 發佈:2019-01-31
在Java 字元終端上獲取輸入有三種方式:
1、java.lang.System.in (目前JDK版本均支援)
2、java.util.Scanner (JDK版本>=1.5)
3、java.io.Console(JDK版本>=1.6),特色:能不回顯密碼字元
(1)BufferedReader
public class TestConsole1 {public static void main(String[] args) {
String str = readDataFromConsole("Please input string:);
System.out.println("The information from console: + str);
}
/**
* Use InputStreamReader and System.in to read data from console
*
* @param prompt
*
* @return input string
*/
private static String readDataFromConsole(String prompt) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = null;
try {
System.out.print(prompt);
str = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
}
(2)JDK 1.5(利用Scanner進行讀取)
public class TestConsole2 {
public static void main(String[] args) {
String str = readDataFromConsole("Please input string:");
System.out.println("The information from console:" + str);
}
/**
* Use java.util.Scanner to read data from console
*
* @param prompt
*
* @return input string
*/
private static String readDataFromConsole(String prompt) {
Scanner scanner = new Scanner(System.in);
System.out.print(prompt);
return scanner.nextLine();
}
}
Scanner還可以很方便的掃描檔案,讀取裡面的資訊並轉換成你要的型別,比如對“2 2.2 3.3 3.33 4.5 done”這樣的資料求和,見如下程式碼:
public class TestConsole4 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("num.txt");
fw.write("2 2.2 3.3 3.33 4.5 done");
fw.close();
System.out.println("Sum is "+scanFileForSum("num.txt"));
}
public static double scanFileForSum(String fileName) throws IOException {
double sum = 0.0;
FileReader fr = null;
try {
fr = new FileReader(fileName);
Scanner scanner = new Scanner(fr);
while (scanner.hasNext()) {
if (scanner.hasNextDouble()) {
sum = sum + scanner.nextDouble();
} else {
String str = scanner.next();
if (str.equals("done")) {
break;
} else {
throw new RuntimeException("File Format is wrong!");
}
}
}
} catch (FileNotFoundException e) {
throw new RuntimeException("File " + fileName + " not found!");
} finally {
if (fr != null)
fr.close();
}
return sum;
}
}
(3)JDK 1.6(利用java.io.Console進行讀取)
JDK6中提供了java.io.Console類專用來訪問基於字元的控制檯裝置.
你的程式如果要與Windows下的cmd或者Linux下的Terminal互動,就可以用Console類代勞.(類似System.in和System.out)
但我們不總是能得到可用的Console, 一個JVM是否有可用的Console依賴於底層平臺和JVM如何被呼叫.
如果JVM是在互動式命令列(比如Windows的cmd)中啟動的,並且輸入輸出沒有重定向到另外的地方,那麼就可以得到一個可用的Console例項。
在使用 IDE 的情況下,是無法獲取到Console例項的,原因在於在 IDE 的環境下,重新定向了標準輸入和輸出流,也是就是將系統控制檯上的輸入輸出重定向到了 IDE 的控制檯中
public class TestConsole3 {
public static void main(String[] args) {
String str = readDataFromConsole("Please input string:");
System.out.println("The information from console:" + str);
}
/**
* Use java.io.console to read data from console
*
* @param prompt
*
* @return input string
*/
private static String readDataFromConsole(String prompt) {
Console console = System.console();
if (console == null) {
throw new IllegalStateException("Console is not available!");
}
return console.readLine(prompt);
}
}
Console類還有個特色就是,專門對密碼(輸入無回顯)等安全字元,進行了處理。專門提供 readPassword()方法,具體應用見如下程式碼:
public class TestConsole5 {
public static void main(String[] args) {
Console console = System.console();
if (console == null) {
throw new IllegalStateException("Console is not available!");
}
while(true){
String username = console.readLine("Username: ");
char[] password = console.readPassword("Password: ");
if (username.equals("Chris") && String.valueOf(password).equals("GoHead")) {
console.printf("Welcome to Java Application %1$s.\n", username);
// 使用後應立即將陣列清空,以減少其在記憶體中佔用的時間,增強安全性
password = null;
System.exit(-1);
}
else {
console.printf("Invalid username or password.\n");
}
}
}
}
System.in讀取標準輸入裝置資料(從標準輸入獲取資料,一般是鍵盤),其資料型別為InputStream。方法:
int read() // 返回輸入數值的ASCII碼,,該值為0到 255範圍內的int位元組值。若返回值為-1,說明沒有讀取到任何位元組讀取工作結束。
int read(byte[] b) // 讀入多個位元組到緩衝區b中,返回值是讀入的位元組數
package InPackage; /** * System.in.read()返回值為輸入數值的ASCII碼,該值為0到 255範圍內的int位元組值 * 如果因為已經到達流末尾而沒有可用的位元組,則返回值 -1。*/ public class Intest1 { public static void main(String args[]) throws java.io.IOException { int a=0; System.out.println("請輸入a:"); a=System.in.read(); System.out.println("a="+a); System.out.println("(char)a="+(char)a); } /** * 假設我們輸入a為1 * 輸出結果為: * 請輸入a: * 1 * a=49 * (char)a=1*/ }
有一個有意思的問題是:當我們輸入一個字元,System.in.read()會讀取幾個字元呢?
package InPackage; import java.util.Arrays; /** * 當我們輸入一個字元,System.in.read()會讀取幾個字元 * 我們從執行結果可以看出是三個 * 假設我們輸入一個字元,那麼它會接著讀取該字元後面的/r和/n */ public class Intest2 { public static void main(String[] args) throws Exception { int[] x = new int[6]; Arrays.fill(x, 5); //Arrays.fill(int[] a,int b)方法用於給陣列中的每個元素賦值 for (int i = 0; i < x.length; i++) { System.in.read(); System.out.println(x[i]); } } /** * 假設我們輸入值分別為1,2 * 輸出結果: * 1 * 5 * 5 * 5 * 2 * 5 * 5 * 5 */ }
System.in.read()每次只是讀取一個字元,但它多讀取的是哪幾個字元呢?
package InPackage; import java.io.IOException; /** * System.in.read()每次只是讀取一個字元 * 按下回車鍵代表了兩個字元\r\n,\r的ASCII碼值是10,\n是13。另外,1對應的ASCII是49 */ public class Intest3 { public static void main(String args[]) throws IOException { for (int j = 0; j < 5; j++) { System.out.println("請輸入:"); char c = 0; c = (char) System.in.read(); if (c == '1') { System.out.println("OK!"); } else { System.out.println((int) c); } } } }
對於上面的程式,我們首先輸入的是w1,結果如下圖所示:
可以看出程式還沒有執行完,阻塞於最後一個“請輸入:”,此時我們再次輸入1,程式執行完成,結果如下圖所示:
如何讓System..in.read()讀入一行資料呢?
package InPackage; import java.io.IOException; public class Intest4 { public static void main(String args[]) { int b; try { System.out.println("請輸入:"); while ((b = System.in.read()) != -1) { System.out.print((char) b); } } catch (IOException e) { System.out.println(e.toString()); } } /** * 輸出結果: * 請輸入: * test * test */ }
package InPackage; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.InputStreamReader; /** * 通常情況下,你會用readLine( )一行一行地讀取輸入, * 因此要把System.in包裝成BufferedReader。但在這之前還得先用InputSteamReader把System.in轉換成Reader。 * BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); * in.readLine()返回值為String型別 * */ public class Intest5 { public static void main(String args[]) throws java.io.IOException { System.out.println("請輸入整數:"); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); //或者這麼寫也可以:DataInputStream reader = new DataInputStream(System.in); int a = Integer.parseInt(reader.readLine()); // 這樣得到的是String型別的,需要轉換為需要的型別 System.out.println("a=" + a); int sum = 0; for (int i = 0; i <= a; i++) sum += i; System.out.println(sum); } /** * 假設我們輸入a為100 * 輸出結果為: * 100 * a=100 * 5050 */ }
public int read(byte[] b) throws IOException又是怎麼使用的呢?
package InPackage; /** * public int read(byte[] b) throws IOException * 從輸入流中讀取一定數量的位元組,並將其儲存在緩衝區陣列 b中。 * 返回值為:以整數形式返回實際讀取的位元組數。 * 如果 b的長度為0,則不讀取任何位元組並返回 0; 否則,嘗試讀取至少一個位元組。 * 如果因為流位於檔案末尾而沒有可用的位元組,則返回值 -1;否則,至少讀取一個位元組並將其儲存在b中。 * */ public class Intest6 { public static void main(String args[]) throws Exception { byte[] barray = new byte[5]; System.out.println("請輸入:"); System.in.read(barray); for (int i = 0; i < barray.length; i++) { System.out.println((char) barray[i]); } } }