简体   繁体   English

尝试从 Java 中的控制台读取

[英]Trying to read from the console in Java

I have just started learning Java with IntelliJ IDE.我刚刚开始使用 IntelliJ IDE 学习 Java。 I know a bit C# so the logic makes some sense, however there is one thing so far I couldn't get over it.我知道一点 C#,所以逻辑是有道理的,但是到目前为止,我无法克服一件事。

How do I read from the console?我如何从控制台读取? In C#, you could easily read what the human typed into it, using Console.ReadLine() .在 C# 中,您可以使用Console.ReadLine()轻松读取人类输入的内容。 In Java, System.console().readLine();在 Java 中, System.console().readLine(); does not work for me and throws a NullPointerException .对我不起作用并抛出NullPointerException

What am I missing here?我在这里缺少什么?

NOTE: problem doesn't appear when we run your code from console/terminal via java [options] [MainClass] so if this is valid solution for you you can stop reading here.注意:当我们通过java [options] [MainClass]控制台/终端运行您的代码时,问题不会出现,因此如果这对您来说是有效的解决方案,您可以停止阅读此处。 Rest of this answer is for people who are using some IDEs to run their code.此答案的其余部分适用于使用某些 IDE 来运行其代码的人。

Problem问题

Most IDEs are using javaw.exe instead of java.exe to run Java code (see image below).大多数 IDE 使用javaw.exe而不是java.exe来运行 Java 代码(见下图)。

Difference between these two programs is that javaw runs Java code without association with current terminal/console (which is useful for GUI applications), and since there is no associated console window System.console() returns null .这两个程序之间的区别在于javaw运行 Java 代码与当前终端/控制台无关(这对 GUI 应用程序很有用),并且由于没有关联的控制台窗口System.console()返回null Because of that System.console().readLine() ends up as null.readLine() which throws NullPointerException since null doesn't have readLine() method (nor any method/field).因为System.console().readLine()最终为null.readLine()抛出NullPointerException因为null没有readLine()方法(也没有任何方法/字段)。

But just because there is no associated console, it doesn't mean that we can't communicate with javaw process.但是仅仅因为没有关联的控制台,并不意味着我们不能与javaw进程通信。 This process still supports standard input/output/error streams, so IDEs process (and via it also we) can use them via System.in , System.out and System.err .这个进程仍然支持标准的输入/输出/错误流,所以 IDE 进程(以及通过它我们)可以通过System.inSystem.outSystem.err使用它们。

This way IDEs can have some tab/window and let it simulate console.这样 IDE 可以有一些选项卡/窗口并让它模拟控制台。

For instance when we run code like in Eclipse:例如,当我们像在 Eclipse 中一样运行代码时:

package com.stackoverflow;

public class Demo {

    public static void main(String[] args) throws Exception {
        System.out.println("hello world");
        System.out.println(System.console());
    }

}

we will see as result我们会看到结果

在此处输入图片说明

which shows that despite javaw.exe not having associated console ( null at the end) IDE was able to handle data from standard output of the javaw process System.out.println("hello world");这表明尽管javaw.exe没有关联的控制台(最后为null ),但 IDE 能够处理来自javaw进程System.out.println("hello world");标准输出的数据System.out.println("hello world"); and show hello world .并显示hello world

General solution通用解决方案

To let user pass information to process use standard input stream ( System.in ).让用户将信息传递给进程使用标准输入流( System.in )。 But since in is simple InputStream and Stream s are meant to handle binary data it doesn't have methods which would let it easily and properly read data as text (especially if encoding can be involved).但由于in是简单的InputStreamStream s 旨在处理二进制数据,因此它没有方法可以让它轻松正确地将数据读取为文本(尤其是在可能涉及编码的情况下)。 That is why Readers and Writers ware added to Java.这就是ReadersWriters ware 添加到 Java 的原因。

So to make life easier and let application read data from user as text you can wrap this stream in one of the Reader s like BufferedReader which will let you read entire line with readLine() method.因此,为了让生活更轻松并让应用程序从用户读取数据作为文本,您可以将此流包装在Reader之一中,例如BufferedReader ,这将让您使用readLine()方法读取整行。 Unfortunately this class doesn't accept Streams but Reader s, so we need some kind of adapter which will simulate Reader and be able to translate bytes to text.不幸的是,这个类不接受Streams而是Reader ,所以我们需要某种适配器来模拟 Reader 并能够将字节转换为文本。 But that is why InputStreamReader exists.但这就是InputStreamReader存在的原因。

So code which would let application read data from input stream could look like所以让应用程序从输入流读取数据的代码看起来像

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);

Preferred/simplest solution - Scanner首选/最简单的解决方案 - 扫描仪

To avoid this magic involving converting Stream to Reader you can use Scanner class, which is meant to read data as text from Streams and Readers.为了避免这种将 Stream 转换为 Reader 的魔法,您可以使用Scanner类,该类旨在从 Streams 和 Readers 读取数据作为文本。

This means you can simply use这意味着您可以简单地使用

Scanner scanner = new Scanner(System.in);
//...
String name = scanner.nextLine();

to read data from user (which will be send by console simulated by IDE using standard input stream).从用户读取数据(将由 IDE 使用标准输入流模拟的控制台发送)。

If you realy need to Console object you can compile your class from command line.如果你真的需要 Console 对象,你可以从命令行编译你的类。 Firstly in my java file first statement is package com.inputOutput;首先在我的 java 文件中,第一条语句是package com.inputOutput;

Go in your project " src " folder and compile it like : " javac com/inputOutput/Password.java " ' com ' and ' inputOutput ' are folder(package).进入你的项目“ src ”文件夹并像这样编译它:“ javac com/inputOutput/Password.java ”“ com ”和“ inputOutput ”是文件夹(包)。 Run your class file in src foldersrc文件夹中运行您的类文件
java com.inputOutput.Password ". It had worked work for me. java com.inputOutput.Password “。它对我java com.inputOutput.Password

You could use an Jframe.您可以使用 Jframe。

JFrame frame = new JFrame("titile");

// prompt the user to enter their code
String code = JOptionPane.showInputDialog(frame, "promt here");

java.util.Scanner API 正是您要找的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM