@@ -192,4 +192,246 @@ public class ThirdJavaForC {
192
192
3.2 在文字模式下與程式互動
193
193
--------------------------
194
194
195
+ 從互動中學習,是我最喜愛的學習方式,我建議學習 Java 的第一步,要先能看到您的程式執行結果,要可以對程式輸入一些資料,作一些傻瓜式的互動。
196
+
197
+ ## 3.2.1 使用 Scanner 取得輸入 ##
198
+
199
+ 在文字模式下要輸入資料至程式中時,您可以使用標準輸入串流物件 System.in,然而實際上很少直接使用它,因為 System.in 物件所提供的 read() 方法,是從輸入串流取得一個位元組的資料,並傳回該位元組的整數值,但通常您要取得的使用者輸入會是一個字串,或是一組數字,所以 System.in 物件的 read() 方法一次只讀入一個位元組資料的方式並不適用。
200
+
201
+ 在 J2SE 5.0 中,您可以使用 java.util.Scanner 類別取得使用者的輸入,java.util 指的是套件(package)層級,java.util.Scanner 表示 Scanner 這個類別是位於 java/util 這樣的階層之下,現階段您可以將這個階層想像為類似檔案管理的目錄階層。
202
+ 直接使用實例來看看如何使用 Scanner 取得使用者的輸入字串:
203
+
204
+ #### ** 範例 3.5 ScannerDemo.java**
205
+ ``` java
206
+ import java.util.Scanner ;
207
+
208
+ public class ScannerDemo {
209
+ public static void main (String [] args ) {
210
+ Scanner scanner = new Scanner (System . in);
211
+ System . out. print(" 請輸入您的名字:" );
212
+ System . out. printf(" 哈囉! %s!\n " , scanner. next());
213
+ }
214
+ }
215
+ ```
216
+
217
+ 先看看執行結果再來解釋程式的內容:
218
+
219
+ 請輸入您的名字:良葛格
220
+ 哈囉! 良葛格!
221
+
222
+ java.util 套件是 Java SE 的標準套件,您使用 import 是在告訴編譯器,您將使用 java.util下 的 Scanner 類別。
223
+
224
+ new 關鍵字表示您要新增一個 Scanner 物件,在新增一個 Scanner 物件時需要一個 System.in 物件,因為實際上還是 System.in 在取得使用者的輸入,您可以將 Scanner 看作是 System.in 物件的支援者,System.in 取得使用者輸入之後,交給 Scanner 作一些處理(實際上,這是 Decorator 模式的一個應用,請見這一章後的索引)。
225
+
226
+ 不以 Java 術語而以白話來說,您告訴執行環境給您一個叫作 Scanner 的工具,然後您可以使用這個工具的 next() 功能,來取得使用者的輸入字串,但要如何取得數字呢?您可以使用 Scanner 工具的 nextInt() 功能,例如:
227
+
228
+ #### ** 範例 3.6 ScannerDemo2.java**
229
+ ``` java
230
+ import java.util.Scanner ;
231
+
232
+ public class ScannerDemo2 {
233
+ public static void main (String [] args ) {
234
+ Scanner scanner = new Scanner (System . in);
235
+ System . out. print(" 請輸入一個數字: " );
236
+ System . out. printf(" 您輸入了 %d !\n " ,
237
+ scanner. nextInt());
238
+ }
239
+ }
240
+ ```
241
+
242
+ nextInt() 會將試著取得的字串轉換為int型態的整數,關於資料型態(Data type)我待會就會介紹,先來看看執行結果:
243
+
244
+ 請輸入一個數字: 100
245
+ 您輸入了 100 !
246
+
247
+ 依同樣的方式,您還可以使用 Scanner 的 nextFloat()、nextBoolean() 等方法來取得使用者的輸入,並轉換為正確的資料型態。
248
+
249
+ 在 JDK6 之中,您還可以使用 System.console() 方法取得一個 java.io.Console 物件,利用它來取得使用者輸入非常的方便,關於 Console 的介紹,請見第 21 章關於 JDK6 新功能的介紹。
250
+
251
+ 3.2.2 使用 BufferedReader 取得輸入
252
+ ----------------------------------
253
+
254
+ Scanner 取得輸入的依據是空白字元,舉凡按下空白鍵、tab 鍵或是 enter 鍵,Scanner 就會傳回下一個輸入,所以在某些時候並不適用,因為使用者可能輸入一個字串,中間會包括空白字元,而您希望取得完整的字串,如果您想要取得包括空白字元的輸入,比較簡單的方法是使用 java.io.BufferedReader 類別取得輸入,這個方法也是在 Java SE 1.4 或之前版本下取得使用者輸入的方式。
255
+
256
+ 必須先說明的是,關於使用 BufferedReader 來取得輸入,在理解上要複雜的多,我在這邊先加以說明,但如果您現階段無法理解的話不用氣餒,因為使用方法是固定的,每次使用前先如法泡製就可以了,在第14章介紹完輸入輸出,您就會理解 BufferedReader 的運作方式。
257
+
258
+ BufferedReader 類別是 java.io 套件中所提供的一個類別,所以使用這個類別時必須使用 import 告訴編譯器這個類別位於 java.io 套件下。
259
+
260
+ 使用 BufferedReader 物件的 readLine() 方法必須處理 java.io.IOException 例外(exception),例外處理機制是 Java 提供給程式設計人員捕捉程式中可能發生的錯誤所提供的機制,現階段您處理 IOException 的方法是在 main() 方法加上 throws IOException,這在第 10 章介紹例外處理時,我會再詳細介紹為何要這麼作。
261
+
262
+ BufferedReader 在建構時接受一個 java.io.Reader 物件,在讀取標準輸入串流時,您可以使用 java.io.InputStreamReader,它繼承(Inherit)了 Reader類別,您可以使用以下的方法來為標準輸入串流建立緩衝區物件:
263
+
264
+ ``` java
265
+ BufferedReader bufferedReader = new BufferedReader (
266
+ new InputStreamReader (System . in));
267
+ ```
268
+
269
+ BufferedReader bufferedReader 表示宣告一個型態為 BufferedReader 的參考名稱,而 new BufferedReader() 表示您以 BufferedReader 類別建構一個物件,new InputStreamReader(System.in) 表示接受一個 System.in 物件來建構一個 InputStreamReader 物件。
270
+
271
+ 不用Java術語而用白話來解釋上一段的話,就是您增加一個 BufferedReader 工具,這個工具中還要加上一個 InputStreamReader 工具,而 InputStreamReader 工具中實際的核心是 System.in 工具,這三個工具組合在一起,就可以讓您進行文字輸入的讀取。
272
+
273
+ 如果還是不理解的話沒關係,照著抄寫就可以了,實際看個例子瞭解如何使用 BufferedReader 來讀取輸入。
274
+
275
+ #### ** 範例 3.7 BufferedReaderDemo.java**
276
+ ``` java
277
+ import java.io.* ;
278
+
279
+ public class BufferedReaderDemo {
280
+ public static void main (String [] args ) throws IOException {
281
+ BufferedReader bufferedReader =
282
+ new BufferedReader (
283
+ new InputStreamReader (System . in));
284
+
285
+ System . out. print(" 請輸入一列文字,可包括空白: " );
286
+ String text = bufferedReader. readLine();
287
+ System . out. println(" 您輸入的文字: " + text);
288
+ }
289
+ }
290
+ ```
291
+
292
+ 由於這次您所使用到的 BufferedReader、InputStreamReader 與 IOException 等類別,都是位在 java.io 套件下,所以在程式的一開頭可以使用 import 與 * 號,告訴編譯器到 java.io 下找這些類別。
293
+
294
+ readLine() 方法會傳回使用者在按下 Enter 鍵之前的所有字元輸入,不包括最後按下的 Enter 返回字元,程式的執行範例如下所示:
295
+
296
+ 請輸入一列文字,可包括空白: Have a nice day :)
297
+ 您輸入的文字: Have a nice day :)
298
+
299
+ > ** 良葛格的話匣子** 學習一個新的事物時,如果遇到一些觀念無法馬上理解,這可能是因為要理解觀念會需要其它觀念先建立起來,所以先暫時放下這個疑問也是一個學習方法,稱之為「闕疑」,在往後的學習過程中待必要的觀念學會後,目前的疑問自然也會解開。
300
+ >
301
+ > 但什麼該闕疑?什麼觀念又該先徹底理解?在這本書中我會根據經驗告訴您,在告訴您闕疑的同時,也會告訴您這些觀念實際上在哪個章節(或網路資料上)會詳細說明。
302
+
303
+ ## 3.2.3 標準輸入輸出串流 ##
304
+
305
+ 在之前的範例程式中,您使用了 System 類別中的靜態物件 out,它提供標準輸出串流(Stream)輸出,會在程式開始執行之後自動開啟並準備接受指定的資料,它通常對應至顯示輸出(文字模式、終端機輸出),您可以將輸出重新導向至一個檔案,只要執行程式時使用'>'將輸出結果導向至指定的檔案,例如:
306
+
307
+ java HelloJava > HelloJavaResult.txt
308
+
309
+ 上面的執行會將原本文字模式下的顯示結果導向至 HelloJavaResult.txt,而不會在螢幕上顯示訊息,HelloJavaResult.txt 將會有執行的結果文字" 嗨!我的第一個Java程式!"。
310
+
311
+ 除了標準輸出串流 out 之外,Java 程式在執行之後,還會開啟標準輸入串流 in 與標準錯誤輸出串流 err。標準輸入串流 in 也是 System 類別所提供的靜態物件,在程式開始之後它會自動開啟,對應至鍵盤或其它的輸入來源,準備接受使用者或其它來源的輸入,您可以使用 read() 方法來讀取輸入,不過通常很少直接使用,而會使用一個 Scanner 物件或 BufferedReader 來讀取輸入,方法我已經在前面的內容介紹過了。
312
+
313
+ 標準錯誤輸出串流 err 也是在程式執行後自動開啟,它會將指定的字串輸出至顯示裝置或其它指定的裝置,與標準輸出串流 out 不同的是,err 會立即顯示指定的(錯誤)訊息給使用者知道,即使您指定程式將結果重新導向至檔案,err 輸出串流的訊息也不會被重新導向,而仍會顯示在指定的顯示裝置上,下面這個例子給您一個簡單的測試方式:
314
+
315
+ #### ** 範例 3.8 ErrDemo.java**
316
+ ``` java
317
+ public class ErrDemo {
318
+ public static void main (String [] args ) {
319
+ System . out. println(" 使用out輸出訊息" );
320
+ System . err. println(" 使用err輸出訊息" );
321
+ }
322
+ }
323
+ ```
324
+
325
+ 在編譯程式之後,請如下執行程式,您會發現輸出結果如下:
326
+
327
+ java ErrDemo > ErrDemoResult.txt
328
+ 使用err輸出訊息
329
+
330
+ 開啟 ErrDemoResult.txt 之後,您會發現當中只有 "使用out輸出訊息" 的文字,而"使用 err 輸出訊息"的文字並沒有被導向至檔案中,而是直接顯示在文字模式中。
331
+
332
+ 要重新導向輸出至指定的目的檔案是用 '>',也可以使用 '>>',後者除了重導標準輸出之外,還有附加(Append)的功能,也就是會把輸出的內容附加到目的檔案的後頭,如果目的檔案本來不存在就會先建立一個再進行輸出。
333
+
334
+ 3.2.4 輸出格式控制
335
+ ------------------
336
+
337
+ 標準輸出通常是使用文字模式作為輸出,這邊我介紹幾個輸出格式控制技巧,在文字模式顯示時可以協助控制輸出的格式,首先介紹格式控制字元,先使用表格列出一些常用的控制字元:
338
+
339
+ #### ** 表 3.1 常用格式控制字元**
340
+ | 控制字元 | 作用 |
341
+ | :-------- | :------ |
342
+ | \\ \ | 反斜線 |
343
+ | \' | 單引號' |
344
+ | \" | 雙引號" |
345
+ | \uxxxx | 以16進位數指定Unicode字元輸出 |
346
+ | \xxx | 以8進位數指定Unicode字元輸出 |
347
+ | \b | 倒退一個字元 |
348
+ | \f | 換頁 |
349
+ | \n | 換行 |
350
+ | \r | 游標移至行首 |
351
+ | \t | 跳格(一個Tab鍵) |
352
+
353
+ 範例 3.9 告訴您如何指定 Unicode 字元編碼來輸出 "Hello" 這段文字。
354
+
355
+ #### ** 範例 3.9 OutputUnicode.java**
356
+ ``` java
357
+ public class OutputUnicode {
358
+ public static void main (String [] args ) {
359
+ System . out. println(" \u 0048\u 0065\u 006C\u 006C\u 006F" );
360
+ }
361
+ }
362
+ ```
363
+
364
+ 在輸出數值時,預設都會以十進位的方式來顯示數值,範例 3.10 告訴您如何使用 java.lang.Integer 所提供的各種 toXXX() 方法來顯示不同進位制之數值。
365
+
366
+ #### ** 範例 3.10 NumberDemo.java**
367
+ ``` java
368
+ public class NumberDemo {
369
+ public static void main (String [] args ) {
370
+ // 十進位 19 轉成二進位 10011
371
+ System . out. println(Integer . toBinaryString(19 ));
372
+
373
+ // 十進位 19 轉成十六進位 13
374
+ System . out. println(Integer . toHexString(19 ));
375
+
376
+ // 十進位 19 轉成八進位 23
377
+ System . out. println(Integer . toOctalString(19 ));
378
+ }
379
+ }
380
+ ````
381
+
382
+ 若是使用 J2SE 5.0 或更高的版本,您可以使用 System . out. printf() 作簡單的輸出格式設定,例如:
383
+
384
+ #### ** 範例 3.11 TigerNumberDemo . java**
385
+ ```java
386
+ public class TigerNumberDemo {
387
+ public static void main (String [] args ) {
388
+ // 輸出 19 的十進位表示
389
+ System . out. printf(" %d%n" , 19 );
390
+
391
+ // 輸出 19 的八進位表示
392
+ System . out. printf(" %o%n" , 19 );
393
+
394
+ // 輸出 19 的十六進位表示
395
+ System . out. printf(" %x%n" , 19 );
396
+ }
397
+ }
398
+ ```
399
+ '%d' 表示將指定的數值以十進位表示,'%o' 是八進位表示,而 '%x' 是十六進位表示,'%n' 是指輸出平台特定的換行字元,如果是在 Windows 下實際上會置換為 'r\n',如果是 Linux 下則會置換為 '\n'。
400
+
401
+ 表3.2 簡單列出了一些常用的轉換符號。
402
+
403
+ #### ** 表 3.2 常用格式轉換字元**
404
+ | 格式字元 | 作用
405
+ | :-------- | :------
406
+ | %% | 在字串中顯示%
407
+ | %d | 以10進位整數方式輸出,提供的數必須是Byte、Short、 Integer、Long、或BigInteger
408
+ | %f | 將浮點數以10進位方式輸出,提供的數必須是Float、Double或 BigDecimal
409
+ | %e, %E | 將浮點數以10進位方式輸出,並使用科學記號,提供的數必須是Float、 Double或BigDecimal
410
+ | %a, %A | 使用科學記號輸出浮點數,以16進位輸出整數部份,以10進位輸出指數部份,提供的數必須是Float、Double、BigDecimal
411
+ | %o | 以8進位整數方式輸出,提供的數必須是Byte、Short、 Integer、Long、或BigInteger
412
+ | %x, %X | 將浮點數以16進位方式輸出,提供的數必須是Byte、Short、 Integer、Long、或BigInteger
413
+ | %s, %S | 將字串格式化輸出
414
+ | %c, %C | 以字元方式輸出,提供的數必須是Byte、Short、Character或 Integer
415
+ | %b, %B | 將"true"或"false"輸出(或"TRUE"、"FALSE",使用 %B)。另外,非null值輸出是"true",null值輸出是"false"
416
+ | %t, %T | 輸出日期/時間的前置,詳請看線上API文件
417
+
418
+ 您可以在輸出浮點數時指定精度,例如以下這行的執行結果會輸出 " example:19.23":
419
+
420
+ System.out.printf("example:%.2f%n", 19.234);
421
+
422
+ 您也可以指定輸出時,至少要預留的字元寬度,例如:
423
+
424
+ System.out.printf("example:%6.2f%n", 19.234);
425
+
426
+ 由於預留了 6 個字元寬度,不足的部份要由空白字元補上,所以執行結果會輸出如下(19.23 只佔五個字元,所以補上一個空白在前端):
427
+
428
+ example: 19.23
429
+
430
+ 以上只是簡短的列出一些常用的輸出轉換符號,事實上,這些功能都是由 [ java.util.Formatter] ( http://java.sun.com/javase/6/docs/api/java/util/Formatter.html ) 所提供的,如果您需要更多關於輸出格式的控制,您可以看看線上 API 文件以查詢相關設定。
431
+
432
+ > ** 良葛格的話匣子** 由於書的篇幅有限,我只在必要的時候列出一些常用的 API 文件表格說明,如果需要更多的說明,請直接查詢我所提供的文件索引,學會查詢線上文件也是學好 Java 的必備功夫喔!
433
+
434
+ 3.3 資料、運算
435
+ --------------
436
+
195
437
待續 ...
0 commit comments