我正在开发一个 Java 程序,该程序会循环直到输入字母
S
。这是代码:
// Loops until the letter S is entered
class ForTest {
public static void main(String[] args)
throws java.io.IOException {
int i;
char x;
System.out.println("Enter 'S' to stop.");
for(i = 0; (x = (char) System.in.read()) != 'S'; i++) {
System.out.println("Iteration " + i + ", read character: " + x);
}
}
}
为什么即使我只输入一个字符(本例中为 L),程序也会显示额外的迭代?
对于像
"h"
这样的单个字符输入,我希望输出是:
Iteration 0, read character: h
但相反,我得到:
Iteration 0, read character: h
Iteration 1, read character:
Iteration 2, read character:
提前致谢!我是 Java 新手,并试图了解在这种情况下事情是如何工作的。
我尝试在循环中打印字符,但最后 2 个字符似乎是空格
默认情况下,java 终端处于所谓的“cooked”模式。熟食模式可以做很多事情。其中之一是,在用户按下 Enter 键之前,不会有任何输入实际发送到您的
System.in
。
换句话说,如果您编写这个非常简单的 Java 应用程序:
void main(String[] args) {
while (true) {
int c = System.in.read();
if (c == -1) break;
System.out.println("CharCode: " + c + " which is character '" + ((char) c) + "'");
}
}
然后你运行它并键入,在击键之间有足够的时间,“h”,“e”,“l”,“l”,“o”,(输入键),然后你的java应用程序不会打印任何内容直到您按下 Enter 键,然后一口气完成所有 6 到 7 个击键。 h、e、两个 ls、一个 o 和“新行”,即代码 13(您可以将其写为
13
、'\n'
或 0x0D
- 它们都表示“13”,并且有因此,这 3 种形式之间绝对没有任何区别 - 无论哪一种使您的代码最具可读性,毫无疑问,在大多数操作系统上都是 '\n'
),但往往是 2 个字符(即 10 后面跟着 13,更易读) ,\r
,然后是 \n
)。
这大概就是您的示例中发生的情况:您按了 h,,然后按了 Enter,这本身也是一个字符。你在 Windows 上,所以实际上是 2 个字符,因此总共 3 次迭代。一根用于
'h'
,一根用于 '\r'
,一根用于 '\n'
。
哦。非常困难。您需要首先告诉操作系统进入未煮过的模式,该模式取决于操作系统,并且java没有烘焙方法来执行此操作,您需要发送适合您的操作系统的魔术序列,并且(2)未煮过的模式有很多缺点。例如,您的输出如下所示:
Enter your name: Joe
Hi Joe!
即'println' 不一定再将光标移回原处,而未煮熟的模式到底有多奇怪取决于操作系统。
如果你想要生的,你需要一个库来简化它,它们确实存在。例如灯笼。但是,实际上,如果您想要更高级的“UI”,而不仅仅是“输入内容并按 Enter”,那么您可能一开始就不应该拥有基于文本的界面,而应将其设为图形界面(通过 swing 或 javafx 或通过执行过去十年每个人都在做的事情,并为其制作了一个网络界面)。
太棒了!然后要读取文本输入,您可能需要这个:
void main(String[] args) {
Scanner s = new Scanner(system.in);
s.useDelimiter("\\R");
System.out.println("Hi there! What is your full name?");
String fullName = s.next();
System.out.println("Good to meet you, " + fullName + "!");
System.out.println("How old are you?");
int age = s.nextInt();
}
注意,有一个
nextLine
方法。不要使用它。它按照其规格说明执行操作,但这不是您所期望的。 next()
已经读取了一整行(因为我们修复了分隔符)。
注意:对于未来的读者 - 这个答案很快就会(几年的时间)过时,正确的答案会变成“使用
java.io.IO
中的静态方法”。由于这仍处于预览阶段,因此它(还)不是这个问题的适当答案。
注意:terminal 默认处于“cooked”模式。如果您将其他任何东西连接到
System.in
,那就不会了。例如,如果您运行 java yourapp.Application <someFile
,则 System.in()
不会逐行缓冲;正如人们所期望的那样,您一次只会获得一个角色。缓冲的事情根本不是由java 完成的; java 只是将 System.in
视为一个简单的管道,并且不会缓冲它,除非您要求将其包装在 BufferedInputStream
中。操作系统/终端正在执行此操作。您可以要求它停止执行此操作 - 但它会停止执行更多操作 - 这称为“请求未煮过的模式”。你..不想要那样,它不适合初学者。