?

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.

要是我們的程序更有意思,我們需要在程序中接收輸入,并適當(dāng)?shù)母袷交敵?。?dāng)然,先進(jìn)的程序采用GUI(圖形用戶界面)來收集用戶輸入。但是編寫這樣一個(gè)界面需要更多的工具和技術(shù),這已經(jīng)超出了我們現(xiàn)在的目標(biāo)。因?yàn)槲覀儺?dāng)前的目標(biāo)是更熟悉Java編程語言,我們還是采用粗陋的控制臺(tái)作為輸入輸出。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.

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

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

要讀取控制臺(tái)輸入,你首先構(gòu)造一個(gè)附屬于標(biāo)準(zhǔn)輸入流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.

現(xiàn)在你可以使用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方法因?yàn)檩斎肟赡馨崭?。要讀取單個(gè)單詞(以空格分隔),調(diào)用:

String firstName = in.next();

To read an integer, use the nextInt method.

要讀取一個(gè)整數(shù),使用nextInt方法。

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

int age = in.nextInt();

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

類似的,nextdouble方法讀取下一個(gè)浮點(diǎn)數(shù)字。

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包里的。只要你使用了一個(gè)沒有定義在基本的java.lang包中的類,你都需要一個(gè)import 命令。我們將在第四章中更詳細(xì)的討論包和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或以上版本,你必須在讀取用戶輸入上多費(fèi)些力氣。最簡單的方法就是使用一個(gè)輸入框(見圖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:

例如,下面的代碼展示了我們?nèi)绾卧诔绦蛑幸筝斎胗脩舻拿帧?

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,

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

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方法將字符串轉(zhuǎn)換為相應(yīng)的數(shù)字值,也就是數(shù)字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.

最后,無論何時(shí)程序調(diào)用JOptionPane.showInputDialog,你需要采用System.exit(0)來結(jié)束之。這是一個(gè)有點(diǎn)技術(shù)性的原因。顯示一個(gè)對(duì)話框需要啟動(dòng)一個(gè)新的控制線程。當(dāng)main方法退出時(shí),新啟動(dòng)的線程并沒有終結(jié)。要結(jié)束所有線程,你需要調(diào)用System.exit方法(想進(jìn)一步了解線程,參見卷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.檢測后面是否還有一個(gè)單詞

  • boolean hasNextInt()
  • boolean hasNextDouble()

test whether the next character sequence represents an integer or floating-point number.檢測下一個(gè)字符序列是否代表一個(gè)整數(shù)或一個(gè)浮點(diǎn)數(shù)。

?

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.
顯示一個(gè)帶有消息提示的對(duì)話框,一個(gè)輸入框,還有”O(jiān)K”和”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.
終止虛擬機(jī)并向操作系統(tǒng)傳遞狀態(tài)碼。約定非零狀態(tài)碼表示一種錯(cuò)誤。

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)語句將一個(gè)數(shù)字x輸出到控制臺(tái)。這個(gè)命令將以該類型最大非零位數(shù)打印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.但是當(dāng)你想顯示美元和美分的時(shí)候這就成了問題。

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前,對(duì)數(shù)字的格式化產(chǎn)生了爭論。幸運(yùn)的是,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個(gè)字符的字段寬度和2個(gè)字符的精度打印出x。也就是說,輸出包含前導(dǎo)空白和七個(gè)字符

3333.33

You can supply multiple parameters to printf, for example:你可以在printf中使用多個(gè)參數(shù)。

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.

每個(gè)格式區(qū)分符以%開始,并被相應(yīng)的變量取代。結(jié)束格式區(qū)分符的轉(zhuǎn)換字符指明了要格式化的值的類型:f是指一個(gè)浮點(diǎn)數(shù)字,s是指一個(gè)字符串,d是指一個(gè)十進(jìn)制整數(shù)。表3-5列出了所有的轉(zhuǎn)換字符。

Table 3-5. Conversions for printf

Conversion Character

Type

Example

d

Decimal integer十進(jìn)制整數(shù)

159

x

Hexadecimal integer十六進(jìn)制整數(shù)

9f

o

Octal integer八進(jìn)制整數(shù)

237

f

Fixed-point floating-point定點(diǎn)浮點(diǎn)數(shù)

15.9

e

Exponential floating-point指數(shù)型浮點(diǎn)數(shù)

1.59e+01

g

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

a

Hexadecimal floating point十六進(jìn)制浮點(diǎn)

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百分號(hào)

%

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)三位毫秒數(shù)

047

N

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

047000000

P

Uppercase morning or afternoon marker大寫上下午標(biāo)記

PM

p

Lowercase morning or afternoon marker小寫上下午標(biāo)記

pm

z

RFC 822 numeric offset from GMT格林尼治時(shí)間偏移量

-0800

Z

Time zone時(shí)區(qū)

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,

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

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

Table 3-6. Flags for printf

Flag

Purpose

Example

+

Prints sign for positive and negative numbers輸出數(shù)字的正負(fù)號(hào)

+3333.33

space

Adds a space before positive numbers在整數(shù)前加一個(gè)空格

| 3333.33|

0

Adds leading zeroes加入前導(dǎo)的0

003333.33

-

Left-justifies field左對(duì)齊字段

|3333.33 |

(

Encloses negative number in parentheses用圓括號(hào)括起負(fù)數(shù)

(3333.33)

,

Adds group separators添加組分隔符

3,333.33

# (for f format)

Always includes a decimal point總是包含小數(shù)點(diǎn)

3,333.

# (for x or o format)

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

0xcafe

^

Converts to upper case轉(zhuǎn)換為大寫

0XCAFE

$

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

159 9F

<

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

159 9F

prints打印出

3,333.33

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

你可以使用多個(gè)標(biāo)記,例如"%,(.2f",使用組分隔符并用圓括號(hào)括住負(fù)數(shù)。

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轉(zhuǎn)換來格式化任意對(duì)象。如果任意對(duì)象實(shí)現(xiàn)了Formattable接口,則對(duì)象的formatTo方法被調(diào)用。否則調(diào)用toString方法來將一個(gè)對(duì)象轉(zhuǎn)變?yōu)橐粋€(gè)字符串。我們將在第五章和第六章中分別討論toString方法和接口

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

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

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方法的時(shí)間和日期格式選項(xiàng)。你可以使用一個(gè)兩字母的格式,以t開始,以表3-7中的字母結(jié)束。例如

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

prints the current date and time in the format

以如下格式輸出日期和時(shí)間。

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中所見,一些格式僅輸出指定時(shí)間的一部分,例如,僅僅是日或者月。如果你要多次提供時(shí)間,并要格式化每個(gè)部分,這看起來很傻。一個(gè)格式化字串可以指定要格式化的參數(shù)的索引。索引值緊跟百分號(hào)%,并以$結(jié)束。例如

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

或者你可以選擇使用<標(biāo)記。它表明將再次使用前一個(gè)格式所規(guī)范的參數(shù)。也就是如下語句

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

yields the same output as the preceding statement.

將和上一條語句產(chǎn)生相同的輸出。

CAUTION

?

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

參數(shù)索引值以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.

一些格式化規(guī)范是地區(qū)性的。例如,在德國,十進(jìn)制分隔符是一個(gè)句點(diǎn),而不是一個(gè)逗號(hào),而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以前版本,請(qǐng)使用NumberFormat和DateFormat來代替printf


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