文档

Java™ 教程
隐藏目录
命令行输入/输出
路径:基本Java类
课程:基本I/O
章节:I/O流

命令行I/O

程序通常从命令行运行,并在命令行环境中与用户交互。Java平台通过两种方式支持这种交互:标准流和控制台。

标准流

标准流是许多操作系统的特性。默认情况下,它们从键盘读取输入并将输出写入显示器。它们还支持文件和程序之间的输入/输出,但该特性由命令行解释器控制,而不是程序本身。

Java平台支持三种标准流:标准输入(通过System.in访问)、标准输出(通过System.out访问)和标准错误(通过System.err访问)。这些对象是自动定义的,不需要打开。标准输出和标准错误都是用于输出;将错误输出分开可以使用户将常规输出重定向到文件,并仍然能够读取错误消息。有关更多信息,请参阅您的命令行解释器的文档。

您可能期望标准流是字符流,但出于历史原因,它们是字节流。System.outSystem.err被定义为PrintStream对象。虽然它在技术上是字节流,但PrintStream利用一个内部字符流对象来模拟许多字符流的功能。

相比之下,System.in是一个没有字符流功能的字节流。要将标准输入用作字符流,可以将System.in包装在InputStreamReader中。

InputStreamReader cin = new InputStreamReader(System.in);

控制台

标准流的更高级替代方案是控制台。这是一种预定义的Console类型的对象,具有标准流提供的大部分功能,以及其他功能。控制台在安全密码输入方面特别有用。控制台对象还通过其readerwriter方法提供真正的字符流的输入和输出流。

在程序使用控制台之前,必须尝试通过调用System.console()来检索控制台对象。如果控制台对象可用,此方法将返回它。如果System.console返回NULL,则不允许使用控制台操作,这可能是因为操作系统不支持它们,或者因为在非交互式环境中启动了程序。

控制台对象通过其readPassword方法支持安全密码输入。该方法通过两种方式帮助确保密码安全输入。首先,它禁止回显,因此密码在用户屏幕上不可见。其次,readPassword返回一个字符数组,而不是String,因此可以覆盖密码,一旦不再需要,即可从内存中删除它。

这个示例是一个用于更改用户密码的原型程序。它演示了几个Console方法。

import java.io.Console;
import java.util.Arrays;
import java.io.IOException;

public class Password {
    
    public static void main (String args[]) throws IOException {

        Console c = System.console();
        if (c == null) {
            System.err.println("没有控制台。");
            System.exit(1);
        }

        String login = c.readLine("请输入您的登录名:");
        char [] oldPassword = c.readPassword("请输入您的旧密码:");

        if (verify(login, oldPassword)) {
            boolean noMatch;
            do {
                char [] newPassword1 = c.readPassword("请输入您的新密码:");
                char [] newPassword2 = c.readPassword("请再次输入新密码:");
                noMatch = ! Arrays.equals(newPassword1, newPassword2);
                if (noMatch) {
                    c.format("密码不匹配,请重试。%n");
                } else {
                    change(login, newPassword1);
                    c.format("%s的密码已更改。%n", login);
                }
                Arrays.fill(newPassword1, ' ');
                Arrays.fill(newPassword2, ' ');
            } while (noMatch);
        }

        Arrays.fill(oldPassword, ' ');
    }
    
    // 虚拟的验证方法。
    static boolean verify(String login, char[] password) {
        // 在这个示例中,这个方法总是返回true。
        // 根据您的规则修改此方法以验证密码。
        return true;
    }

    // 虚拟的更改方法。
    static void change(String login, char[] password) {
        // 根据您的规则修改此方法以更改密码。
    }
}

Password类遵循以下步骤:

  1. 尝试检索Console对象。如果对象不可用,则中止。
  2. 调用Console.readLine提示并读取用户的登录名。
  3. 调用Console.readPassword提示并读取用户的现有密码。
  4. 调用verify确认用户是否有权更改密码。(在这个示例中,verify是一个虚拟方法,总是返回true。)
  5. 重复以下步骤,直到用户两次输入相同的密码:
    1. 调用Console.readPassword两次提示并读取新密码。
    2. 如果用户两次输入的密码相同,调用change来更改密码。(同样,change是一个虚拟方法。)
    3. 用空格覆盖两个密码。
  6. 用空格覆盖旧密码。

上一页: 格式化
下一页: 数据流