?

To make our example programs more interesting, we want to accept input and properly format the program output. Of course, modern programs use a GUI for collecting user input. However, programming such an interface requires more tools and techniques than we have at our disposal at this time. Because the first order of business is to become more familiar with the Java programming language, we make do with the humble console for input and output for now. GUI programming is covered in Chapters 7 through 9.

要是我們的程序更有意思,我們需要在程序中接收輸入,并適當的格式化輸出。當然,先進的程序采用GUI(圖形用戶界面)來收集用戶輸入。但是編寫這樣一個界面需要更多的工具和技術,這已經超出了我們現在的目標。因為我們當前的目標是更熟悉Java編程語言,我們還是采用粗陋的控制臺作為輸入輸出。GUI編程將在7~9章介紹。

Reading Input 讀取輸入

You saw that it is easy to print output to the "standard output stream" (that is, the console window) just by calling System.out.println. Oddly enough, before JDK 5.0, there was no convenient way to read input from the console window. Fortunately, that situation has finally been rectified.

你可以看到,向標準輸出流(也就是控制臺窗口)輸出內容非常簡單,只需要調用System.out.println即可。非常奇怪的是,JDK5.0以前,還沒有什么便捷的辦法可以從控制臺窗口讀取輸入。幸運的是,這種情況最終得以矯正。

To read console input, you first construct a Scanner that is attached to the "standard input stream" System.in.

要讀取控制臺輸入,你首先構造一個附屬于標準輸入流System.in的Scanner。

Scanner in = new Scanner(System.in);

Now you use the various methods of the Scanner class to read input. For example, the nextLine method reads a line of input.

現在你可以使用Scanner類的各種方法來讀取輸入。例如,nextLine方法可以讀取一行輸入。

System.out.print("What is your name? ");

String name = in.nextLine();

Here, we use the nextLine method because the input might contain spaces. To read a single word (delimited by whitespace), call

這里,我們使用nextLine方法因為輸入可能包含空格。要讀取單個單詞(以空格分隔),調用:

String firstName = in.next();

To read an integer, use the nextInt method.

要讀取一個整數,使用nextInt方法。

System.out.print("How old are you? ");

int age = in.nextInt();

Similarly, the nextdouble method reads the next floating-point number.

類似的,nextdouble方法讀取下一個浮點數字。

The program in Example 3-2 asks for the user's name and age and then prints a message like

Hello, Cay. Next year, you'll be 46

Finally, add the line

import java.util.*;

at the beginning of the program. The Scanner class is defined in the java.util package. Whenever you use a class that is not defined in the basic java.lang package, you need to use an import directive. We look at packages and import directives in more detail in Chapter 4.

例3-2要求用戶輸入姓名和年齡,并輸出消息”Hello, cay. Next year, you’ll be 46”

最后在程序的開頭加上import java.util.*;

Scanner類是定義在java.util包里的。只要你使用了一個沒有定義在基本的java.lang包中的類,你都需要一個import 命令。我們將在第四章中更詳細的討論包和import。

Example 3-2. InputTest.java

1. import java.util.*;

2.

3. public class InputTest

4. {

5. public static void main(String[] args)

6. {

7. Scanner in = new Scanner(System.in);

8.

9. // get first input

10. System.out.print("What is your name? ");

11. String name = in.nextLine();

12.

13. // get second input

14. System.out.print("How old are you? ");

15. int age = in.nextInt();

16.

17. // display output on console

18. System.out.println("Hello, " + name + ". Next year, you'll be " + (age + 1));

19. }

20. }

NOTE

?

If you do not have JDK 5.0 or above, you have to work harder to read user input. The simplest method is to use an input dialog (see Figure 3-6).

如果你沒有JDK 5.0或以上版本,你必須在讀取用戶輸入上多費些力氣。最簡單的方法就是使用一個輸入框(見圖3-6)

String input = JOptionPane.showInputDialog(promptString)

Figure 3-6. An input dialog

G:\temp\Core Java 7th\Core Java I 7th\images\03fig06.jpg

The return value is the string that the user typed.

返回值就是用戶輸入的字符串。

For example, here is how you can query the name of the user of your program:

例如,下面的代碼展示了我們如何在程序中要求輸入用戶的名字。

String name = JOptionPane.showInputDialog("What is your name?");

Reading numbers requires an additional step. The JOptionPane.showInputDialog method returns a string, not a number. You use the Integer.parseInt or Double.parseDouble method to convert the string to its numeric value. For example,

讀取數字型輸入需要再多一步。JOptionPane.showInputDialog方法返回一個字符串,而不是一個數字。你需要使用Integer.parseInt或者Double.parseDouble方法來將其數字值轉換為字符串。例如

String input = JOptionPane.showInputDialog("How old are you?"); int age = Integer.parseInt(input);

If the user types 45, then the string variable input is set to the string "45". The Integer.parseInt method converts the string to its numeric value, the number 45.

如果用戶輸入45,則字符串變量被賦值為”45”。Integer.parseInt方法將字符串轉換為相應的數字值,也就是數字45。

The JOptionPane class is defined in the javax.swing package, so you need to add the statement

JOptionPane類是定義在javax.swing包中,所以你需要添加語句

import javax.swing.*;

Finally, whenever your program calls JOptionPane.showInputDialog, you need to end it with a call to System.exit(0). The reason is a bit technical. Showing a dialog box starts a new thread of control. When the main method exits, the new thread does not automatically terminate. To end all threads, you call the System.exit method. (For more information on threads, see Chapter 1 of Volume 2.) The following program is the equivalent to Example 3-2 prior to JDK 5.0.

最后,無論何時程序調用JOptionPane.showInputDialog,你需要采用System.exit(0)來結束之。這是一個有點技術性的原因。顯示一個對話框需要啟動一個新的控制線程。當main方法退出時,新啟動的線程并沒有終結。要結束所有線程,你需要調用System.exit方法(想進一步了解線程,參見卷2第一章)下面的程序等同于JDK5.0以前的例3-2

import javax.swing.*;

public class InputTest

{

public static void main(String[] args)

{

String name = JOptionPane.showInputDialog("What is your name?");

String input = JOptionPane.showInputDialog("How old are you?");

int age = Integer.parseInt(input);

System.out.println("Hello, " + name + ". Next year, you'll be " + (age + 1));

System.exit(0);

}

}

?

java.util.Scanner 5.0

  • Scanner(InputStream in)

constructs a Scanner object from the given input stream.

  • String nextLine()

reads the next line of input.

  • String next()

reads the next word of input (delimited by whitespace).

  • int nextInt()
  • double nextDouble()

read and convert the next character sequence that represents an integer or floating-point number.

  • boolean hasNext()

tests whether there is another word in the input.檢測后面是否還有一個單詞

  • boolean hasNextInt()
  • boolean hasNextDouble()

test whether the next character sequence represents an integer or floating-point number.檢測下一個字符序列是否代表一個整數或一個浮點數。

?

javax.swing.JOptionPane 1.2

  • static String showInputDialog(Object message)

displays a dialog box with a message prompt, an input field, and "OK" and "Cancel" buttons. The method returns the string that the user typed.
顯示一個帶有消息提示的對話框,一個輸入框,還有”OK”和”Cancel”按鈕。該方法返回用戶鍵入的字符串。

?

java.lang.System 1.0

  • static void exit(int status)

terminates the virtual machine and passes the status code to the operating system. By convention, a non-zero status code indicates an error.
終止虛擬機并向操作系統傳遞狀態碼。約定非零狀態碼表示一種錯誤。

Formatting Output 格式化輸出

You can print a number x to the console with the statement System.out.print(x). That command will print x with the maximum number of non-zero digits for that type. For example,

你可以用System.out.print(x)語句將一個數字x輸出到控制臺。這個命令將以該類型最大非零位數打印x。例如:

double x = 10000.0 / 3.0;

System.out.print(x);

prints打印出

3333.3333333333335

That is a problem if you want to display, for example, dollars and cents.但是當你想顯示美元和美分的時候這就成了問題。

Before JDK 5.0, formatting numbers was a bit of a hassle. Fortunately, JDK 5.0 brought back the venerable printf method from the C library. For example, the call

JDK5.0前,對數字的格式化產生了爭論。幸運的是,JDK5.0將古老的printf方法從C庫中帶回來了。例如:

System.out.printf("%8.2f", x);

prints x with a field width of 8 characters and a precision of 2 characters. That is, the printout contains a leading space and the seven characters

以8個字符的字段寬度和2個字符的精度打印出x。也就是說,輸出包含前導空白和七個字符

3333.33

You can supply multiple parameters to printf, for example:你可以在printf中使用多個參數。

System.out.printf("Hello, %s. Next year, you'll be %d", name, age);

Each of the format specifiers that start with a % character is replaced with the corresponding argument. The conversion character that ends a format specifier indicates the type of the value to be formatted: f is a floating-point number, s a string, and d a decimal integer. Table 3-5 shows all conversion characters.

每個格式區分符以%開始,并被相應的變量取代。結束格式區分符的轉換字符指明了要格式化的值的類型:f是指一個浮點數字,s是指一個字符串,d是指一個十進制整數。表3-5列出了所有的轉換字符。

Table 3-5. Conversions for printf

Conversion Character

Type

Example

d

Decimal integer十進制整數

159

x

Hexadecimal integer十六進制整數

9f

o

Octal integer八進制整數

237

f

Fixed-point floating-point定點浮點數

15.9

e

Exponential floating-point指數型浮點數

1.59e+01

g

General floating-point (the shorter of e and f)

a

Hexadecimal floating point十六進制浮點

0x1.fccdp3

s

String

Hello

c

Character

H

b

Boolean

TRue

h

Hash code哈希碼

42628b2

tx

Date and time

See Table 3-7

%

The percent symbol百分號

%

n

The platform-dependent line separator換行符

Table 3-7. Date and Time Conversion Characters

Conversion Character

Type

Example

C

Complete date and time

Mon Feb 09 18:05:19 PST 2004

F

ISO 8601 date

2004-02-09

D

U.S. formatted date (month/day/year)

02/09/2004

T

24-hour time

18:05:19

r

12-hour time

06:05:19 pm

R

24-hour time, no seconds

18:05

Y

Four-digit year (with leading zeroes)

2004

y

Last two digits of the year (with leading zeroes)

04

C

First two digits of the year (with leading zeroes)

20

B

Full month name

February

b or h

Abbreviated month name月份名稱縮寫

Feb

m

Two-digit month (with leading zeroes)

02

d

Two-digit day (with leading zeroes)

09

e

Two-digit day (without leading zeroes)

9

A

Full weekday name

Monday

a

Abbreviated weekday name

Mon

j

Three-digit day of year (with leading zeroes), between 001 and 366

069

H

Two-digit hour (with leading zeroes), between 00 and 23

18

k

Two-digit hour (without leading zeroes), between 0 and 23

18

I

Two-digit hour (with leading zeroes), between 01 and 12

06

l

Two-digit hour (without leading zeroes), between 1 and 12

6

M

Two-digit minutes (with leading zeroes)

05

S

Two-digit seconds (with leading zeroes)

19

L

Three-digit milliseconds (with leading zeroes)三位毫秒數

047

N

Nine-digit nanoseconds (with leading zeroes)九位納秒數

047000000

P

Uppercase morning or afternoon marker大寫上下午標記

PM

p

Lowercase morning or afternoon marker小寫上下午標記

pm

z

RFC 822 numeric offset from GMT格林尼治時間偏移量

-0800

Z

Time zone時區

PST

s

Seconds since 1970-01-01 00:00:00 GMT

1078884319

E

Milliseconds since 1970-01-01 00:00:00 GMT

1078884319047

In addition, you can specify flags that control the appearance of the formatted output. Table 3-6 shows all flags. For example, the comma flag adds group separators. That is,

另外,你可以指定標記來控制格式化輸出的行為。例如逗號標記可以添加組分隔符。也就是

System.out.printf("%,.2f", 10000.0 / 3.0);

Table 3-6. Flags for printf

Flag

Purpose

Example

+

Prints sign for positive and negative numbers輸出數字的正負號

+3333.33

space

Adds a space before positive numbers在整數前加一個空格

| 3333.33|

0

Adds leading zeroes加入前導的0

003333.33

-

Left-justifies field左對齊字段

|3333.33 |

(

Encloses negative number in parentheses用圓括號括起負數

(3333.33)

,

Adds group separators添加組分隔符

3,333.33

# (for f format)

Always includes a decimal point總是包含小數點

3,333.

# (for x or o format)

Adds 0x or 0 prefix添加0x或者0前綴

0xcafe

^

Converts to upper case轉換為大寫

0XCAFE

$

Specifies the index of the argument to be formatted; for example, %1$d %1$x prints the first argument in decimal and hexadecimal指定要格式化的參數的索引,例如%1$d %1$x以十進制和十六進制形式輸出第一個參數

159 9F

<

Formats the same value as the previous specification; for example, %d %<x prints the same number in decimal and hexadecimal格式化前面指定的相同的值,例如%d %<x 以十進制和十六進制的形式輸出同一個數字。

159 9F

prints打印出

3,333.33

You can use multiple flags, for example, "%,(.2f", to use group separators and enclose negative numbers in parentheses.

你可以使用多個標記,例如"%,(.2f",使用組分隔符并用圓括號括住負數。

NOTE

?

You can use the s conversion to format arbitrary objects. If an arbitrary object implements the Formattable interface, the object's formatTo method is invoked. Otherwise, the toString method is invoked to turn the object into a string. We discuss the toString method in Chapter 5 and interfaces in Chapter 6.

你可以使用s轉換來格式化任意對象。如果任意對象實現了Formattable接口,則對象的formatTo方法被調用。否則調用toString方法來將一個對象轉變為一個字符串。我們將在第五章和第六章中分別討論toString方法和接口

You can use the static String.format method to create a formatted string without printing it:

你可使用靜態方法String.format來創建格式化的字符串,而并不將其輸出。

String message = String.format("Hello, %s. Next year, you'll be %d", name, age);

Although we do not describe the Date type in detail until Chapter 4, we do, in the interest of completeness, briefly discuss the date and time formatting options of the printf method. You use two a two-letter format, starting with t and ending in one of the letters of Table 3-7. For example,

盡管我們到第4章才講述Date類型,但是完全是出于興趣,簡要介紹一下printf方法的時間和日期格式選項。你可以使用一個兩字母的格式,以t開始,以表3-7中的字母結束。例如

System.out.printf("%tc", new Date());

prints the current date and time in the format

以如下格式輸出日期和時間。

Mon Feb 09 18:05:19 PST 2004

As you can see in Table 3-7, some of the formats yield only a part of a given date, for example, just the day or just the month. It would be a bit silly if you had to supply the date multiple times to format each part. For that reason, a format string can indicate the index of the argument to be formatted. The index must immediately follow the %, and it must be terminated by a $. For example,

如你在表3-7中所見,一些格式僅輸出指定時間的一部分,例如,僅僅是日或者月。如果你要多次提供時間,并要格式化每個部分,這看起來很傻。一個格式化字串可以指定要格式化的參數的索引。索引值緊跟百分號%,并以$結束。例如

System.out.printf("%1$s %2$tB %2$te, %2$tY", "Due date:", new Date());

prints輸出

Due date: February 9, 2004

Alternatively, you can use the < flag. It indicates that the same argument as in the preceding format specification should be used again. That is, the statement

或者你可以選擇使用<標記。它表明將再次使用前一個格式所規范的參數。也就是如下語句

System.out.printf("%s %tB %<te, %<tY", "Due date:", new Date());

yields the same output as the preceding statement.

將和上一條語句產生相同的輸出。

CAUTION

?

Argument index values start with 1, not with 0: %1$... formats the first argument. This avoids confusion with the 0 flag.

參數索引值以1開始,而不是0.

You have now seen all features of the printf method. Figure 3-7 shows a syntax diagram for format specifiers.

下圖是格式化說明符的語法:

Figure 3-7. Format specifier syntax

[View full size image]

G:\temp\Core Java 7th\Core Java I 7th\images\03fig07.gif

NOTE

?

A number of the formatting rules are locale specific. For example, in Germany, the decimal separator is a period, not a comma, and Monday is formatted as Montag. You will see in Volume 2 how to control the international behavior of your applications.

一些格式化規范是地區性的。例如,在德國,十進制分隔符是一個句點,而不是一個逗號,而Monday被格式化為Montag。你將在卷2中看到如何在你的程序中處理國際化問題。

TIP

?

If you use a version of Java prior to JDK 5.0, use the NumberFormat and DateFormat classes instead of printf.

如果你使用的是JDK5.0以前版本,請使用NumberFormat和DateFormat來代替printf


文章來源:http://x-spirit.spaces.live.com/Blog/cns!CC0B04AE126337C0!335.entry