1. 程式人生 > >Java 字元終端上獲取輸入 System.in

Java 字元終端上獲取輸入 System.in

在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]);
        }
    }
}