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