我刚开始用IntelliJ IDE学习Java,我知道一点C#,所以逻辑上有点道理,但是有一件事到目前为止我还是不能克服。如何从控制台读取?在C#中,使用Console.ReadLine()可以很容易地读取用户输入的内容。在Java中,System.console().readLine();不起作用,并抛出NullPointerException。我错过了什么?
Console.ReadLine()
System.console().readLine();
NullPointerException
6kkfgxo01#
注意:当我们通过java [options] [MainClass]从控制台/终端运行代码时,问题不会出现,所以如果这对你来说是有效的解决方案,你可以停止阅读这里。这个答案的其余部分是为使用一些IDE运行代码的人准备的。
java [options] [MainClass]
大多数IDE使用javaw.exe而不是java.exe来运行Java代码(见下图)。这两个程序的区别在于javaw运行Java代码 * 而不与当前终端/控制台关联 *(这对于GUI应用程序是有用的),并且由于没有关联的控制台窗口,System.console()返回null。因此,System.console().readLine()以null.readLine()结束,null.readLine()抛出NullPointerException,因为null没有readLine()方法(也不是任何方法/字段)。但是没有关联的控制台并不意味着我们不能与javaw进程通信,这个进程仍然支持标准的输入/输出/错误流,所以IDE进程(我们也可以通过它)可以通过System.in、System.out和System.err使用它们。这样,IDE可以有一些选项卡/窗口,并让它 * 模拟 * 控制台。例如,当我们在Eclipse中运行代码时:
javaw.exe
java.exe
javaw
System.console()
null
System.console().readLine()
null.readLine()
readLine()
System.in
System.out
System.err
package com.stackoverflow; public class Demo { public static void main(String[] args) throws Exception { System.out.println("hello world"); System.out.println(System.console()); } }
我们将看到结果
这表明尽管javaw.exe没有关联的控制台(最后是null),IDE仍能够处理来自javaw进程System.out.println("hello world");的标准输出的数据并显示hello world。
System.out.println("hello world");
hello world
让用户使用标准输入流将信息传递给进程但是,由于in是简单的InputStream和Stream,它们旨在处理 * 二进制 * 数据,因此,它不具有使其能够轻松且正确地将数据读取为文本的方法(特别是如果可能涉及编码的话)。这就是为什么Readers和Writers被添加到Java中。因此,为了让应用程序更轻松地从用户那里读取文本数据,您可以将此流 Package 在Reader中,如BufferedReader,这将允许您使用readLine()方法读取整行。不幸的是,此类不接受Streams,但接受Reader。所以我们需要某种 * 适配器 * 来模拟Reader并能够将字节转换为文本。但这就是InputStreamReader存在的原因。因此,允许应用程序从输入流读取数据的代码可能如下所示
in
InputStream
Stream
Readers
Writers
Reader
BufferedReader
Streams
InputStreamReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.print("Hello. Please write your name: "); String name = br.readLine(); System.out.println("Your name is: "+name);
为了避免这种将Stream转换为Reader的“魔法”,您可以使用Scanner类,该类旨在将数据作为文本从Streams和Reader中读取。这意味着您只需使用
Scanner
Scanner scanner = new Scanner(System.in); //... String name = scanner.nextLine();
从用户读取数据(将通过IDE模拟的控制台使用标准输入流发送)。
hm2xizp92#
如果你真的需要控制台对象,你可以从命令行编译你的类。首先在我的java文件的第一个语句是package com.inputOutput;进入你的项目“src“文件夹并编译它:“javac com/inputOutput/Password.java“”com“和”inputOutput“是文件夹(包)。请运行src文件夹中的类文件java com.inputOutput.Password“。它对我很有效。
package com.inputOutput;
src
javac com/inputOutput/Password.java
com
inputOutput
java com.inputOutput.Password
dnph8jn43#
您可以使用Jframe。
JFrame frame = new JFrame("titile"); // prompt the user to enter their code String code = JOptionPane.showInputDialog(frame, "promt here");
hsgswve44#
通常情况下,Console对象需要操作系统提供一个有效的tty,但是IntelliJ IDEA输出窗口不提供。以独立于操作系统的方式完成这一点并不容易。不仅IntelliJ IDEA受到影响。您也不能在jshell中使用System.console():
Console
| Welcome to JShell -- Version 17.0.6 | For an introduction type: /help intro jshell> System.console() $1 ==> null jshell>
在Java 20中,这个问题已得到部分解决。现在,您可以添加VM选项-Djdk.console=jdk.internal.le。请转到“编辑运行/调试配置”,然后依次选择“修改选项”、“添加VM选项”并在此处键入该选项。之后,System.console()将在IDE中工作。它将挂接到IDE已拦截的System.in。请注意,此解决方案没有文档说明,也不受支持,因此可能无法在未来的Java版本中使用。您可以在此JDK issue中找到更多信息。
-Djdk.console=jdk.internal.le
mitkmikd5#
java.util.Scanner API就是你要找的。
java.util.Scanner
5条答案
按热度按时间6kkfgxo01#
注意:当我们通过
java [options] [MainClass]
从控制台/终端运行代码时,问题不会出现,所以如果这对你来说是有效的解决方案,你可以停止阅读这里。这个答案的其余部分是为使用一些IDE运行代码的人准备的。问题
大多数IDE使用
javaw.exe
而不是java.exe
来运行Java代码(见下图)。这两个程序的区别在于
javaw
运行Java代码 * 而不与当前终端/控制台关联 *(这对于GUI应用程序是有用的),并且由于没有关联的控制台窗口,System.console()
返回null
。因此,System.console().readLine()
以null.readLine()
结束,null.readLine()
抛出NullPointerException
,因为null
没有readLine()
方法(也不是任何方法/字段)。但是没有关联的控制台并不意味着我们不能与
javaw
进程通信,这个进程仍然支持标准的输入/输出/错误流,所以IDE进程(我们也可以通过它)可以通过System.in
、System.out
和System.err
使用它们。这样,IDE可以有一些选项卡/窗口,并让它 * 模拟 * 控制台。
例如,当我们在Eclipse中运行代码时:
我们将看到结果
这表明尽管
javaw.exe
没有关联的控制台(最后是null
),IDE仍能够处理来自javaw
进程System.out.println("hello world");
的标准输出的数据并显示hello world
。一般溶液
让用户使用标准输入流将信息传递给进程但是,由于
in
是简单的InputStream
和Stream
,它们旨在处理 * 二进制 * 数据,因此,它不具有使其能够轻松且正确地将数据读取为文本的方法(特别是如果可能涉及编码的话)。这就是为什么Readers
和Writers
被添加到Java中。因此,为了让应用程序更轻松地从用户那里读取文本数据,您可以将此流 Package 在
Reader
中,如BufferedReader
,这将允许您使用readLine()
方法读取整行。不幸的是,此类不接受Streams
,但接受Reader
。所以我们需要某种 * 适配器 * 来模拟Reader并能够将字节转换为文本。但这就是InputStreamReader
存在的原因。因此,允许应用程序从输入流读取数据的代码可能如下所示
首选/最简单的解决方案-扫描仪
为了避免这种将Stream转换为Reader的“魔法”,您可以使用
Scanner
类,该类旨在将数据作为文本从Streams和Reader中读取。这意味着您只需使用
从用户读取数据(将通过IDE模拟的控制台使用标准输入流发送)。
hm2xizp92#
如果你真的需要控制台对象,你可以从命令行编译你的类。首先在我的java文件的第一个语句是
package com.inputOutput;
进入你的项目“
src
“文件夹并编译它:“javac com/inputOutput/Password.java
“”com
“和”inputOutput
“是文件夹(包)。请运行src
文件夹中的类文件java com.inputOutput.Password
“。它对我很有效。dnph8jn43#
您可以使用Jframe。
hsgswve44#
通常情况下,
Console
对象需要操作系统提供一个有效的tty,但是IntelliJ IDEA输出窗口不提供。以独立于操作系统的方式完成这一点并不容易。不仅IntelliJ IDEA受到影响。您也不能在jshell中使用System.console()
:在Java 20中,这个问题已得到部分解决。现在,您可以添加VM选项
-Djdk.console=jdk.internal.le
。请转到“编辑运行/调试配置”,然后依次选择“修改选项”、“添加VM选项”并在此处键入该选项。之后,System.console()
将在IDE中工作。它将挂接到IDE已拦截的System.in
。请注意,此解决方案没有文档说明,也不受支持,因此可能无法在未来的Java版本中使用。您可以在此JDK issue中找到更多信息。
mitkmikd5#
java.util.Scanner
API就是你要找的。