一个非常简单的 java do...while 循环

A very simple java do...while loop

我正在学习 JAVA 并输入了以下 DO...WHILE 示例。如果我键入 'q',程序将退出。它运行但为什么我得到三行 "Please a key followed by ENTER:"?

class DWDemo {
    public static void main (String args[])
      throws java.io.IOException {
          char ch;
          do {
              System.out.println("Please a key followed by ENTER:");
              ch = (char) System.in.read();
          } while (ch != 'q');
      }
}

我假设读取为输入的内容包含您的 ENTER 按键。由于您在 Windows,这包括 CRFL 行结尾。

因此,每次输入字符时,实际上输入了 3 个字符。对于您的第一个输入:

  1. 一个
  2. CR
  3. LF

尝试通过 BufferedReader 和 运行 空白 trim 读取整行,或者只评估其第一个字符。

因为当你键入 a 并点击 Enter 时,in.read() 方法 return 的三个字符 - 'a',回车字符 return \r 和换行符 ('\n')。 (请注意组合 \r\n 在 Windows 下被视为换行符)。

如果您在 Linux 或 OSX 下 运行 您的程序将有明显不同的行为,因为换行符特定于 OS 你正在 运行 启动程序。例如在Linux下就是\n,在OSX-9下就是\r

作为变通方法,您可以读取整行(通过使用 Scanner)并 trim 它,这将省略换行符(忽略 OS类型):

public static void main (String args[]) throws java.io.IOException {
      String line;
      Scanner sc = new Scanner(System.in);
      do {
          System.out.println("Please a key followed by ENTER:");
          line = sc.readLine().trim();
      } while (!"q".equals(line));
  }

在 Windows 系统的命令行中键入输入时,所有行都以由字符 \r\n 组成的换行符结束。所以当你第一次输入 a 时,你实际上输入的是 a\r\n

当代码 System.in.read() 为 运行 时,它只读取已输入缓冲区的第一个字符,在本例中为 a。然后循环 运行s,打印出您的提示并尝试读取缓冲区中的下一个字符。在这种情况下,\r\n 仍在缓冲区中,因此它读入 \r。再次循环并读入 \n。最后它第三次打印提示,因为缓冲区是空的,它等待你的输入。

为了避免这种情况,我建议使用不同的方法从命令行读取,而不是 System.In。也许 Scanner class 更合适。

你必须注意的一件事是 System.in.read() 只接受 1 个字节的输入。请参阅文档 here。因此,当您输入一个字符 a 时,这已经是一个字节,通过输入一个额外的 ENTER 键,字符:\r\n,即将被 read() 捕获两次,这会触发额外的循环迭代和打印逻辑。

正如@kasoban 所说,它们是 CR 和 LF。就是重复3次,但是会根据OS变化。所以我建议你使用扫描仪。您可以在下面找到示例

public class DW {
    public static void main (String args[]) throws java.io.IOException {
      String s;
      Scanner scanner = new Scanner(System.in);
      do {
          System.out.println("Please a key followed by ENTER:");
          s = scanner.nextLine();
        } while (!"q".equals(s));
      }
    }