Trying to read from the console in Java
Asked Answered
T

7

51

I have just started learning Java with IntelliJ IDE. I know a bit C# so the logic makes some sense, however there is one thing so far I couldn't get over it.

How do I read from the console? In C#, you could easily read what the human typed into it, using Console.ReadLine(). In Java, System.console().readLine(); does not work for me and throws a NullPointerException.

What am I missing here?

Tresatrescha answered 20/10, 2014 at 16:57 Comment(3)
Look into the Scanner class, it should give you what you're looking for.Leeanneleeboard
First result for googling last words from title of your question: "read from console JAVA" gives: Java: How to get input from System.console(). Also System.console().readLine(); works fine for me (if I run my code via console, outside of IDE). We need to see your code and know how are you using it and what exception you are getting.Fracas
possible duplicate of Reading and writing to console in JavaDilapidate
F
88

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. Rest of this answer is for people who are using some IDEs to run their code.

Problem

Most IDEs are using javaw.exe instead of java.exe to run Java code (see image below).

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

But just because there is no associated console, it doesn't mean that we can't communicate with javaw process. 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.

This way IDEs can have some tab/window and let it simulate console.

For instance when we run code like in 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

enter image description here

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"); and show hello world.

General solution

To let user pass information to process use standard input stream (System.in). But since in is simple InputStream and Streams 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). That is why Readers and Writers ware added to Java.

So to make life easier and let application read data from user as text you can wrap this stream in one of the Readers like BufferedReader which will let you read entire line with readLine() method. Unfortunately this class doesn't accept Streams but Readers, so we need some kind of adapter which will simulate Reader and be able to translate bytes to text. But that is why InputStreamReader exists.

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.

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

Fracas answered 20/10, 2014 at 19:5 Comment(3)
If one is trying to use Console.readPassword(), the fact that most IDEs don't supply a Console is a killer. java.io.InputStream, java.io.Reader, java.io.Console, and java.util.Scanner all descend directly from java.lang.Object and have no interfaces in common.Illeetvilaine
Interestingly, java.exe provides System.console()!=null when ran from the command line, but provides System.console()==null whan ran from the Eclipse IDE (tried with Oracle JDK9/JDK10 and Eclipse Neon3)Koestler
I was getting this error: java.util.NoSuchElementException: No line found. The solution was run the main class instead of a gradle taskBeatitude
P
3

Normally, the Console object requires a valid tty provided by an operating system, but IntelliJ IDEA output window does not provide one. It's not very trivial to do this in OS-independent way. Not only IntelliJ IDEA is affected. You cannot use System.console() in jshell as well:

|  Welcome to JShell -- Version 17.0.6
|  For an introduction type: /help intro

jshell> System.console()
$1 ==> null

jshell>

In Java 20, this issue was partially addressed. Now, you can add a VM option -Djdk.console=jdk.internal.le. Go to 'Edit Run/Debug configurations', then Modify Options, Add VM Options and type it there. After that the System.console() will work inside IDE. It will be hooked to System.in which IDE already intercepts.

Note that this solution is undocumented and unsupported, so may not work in future Java versions. You can find more information in this JDK issue.

Pronoun answered 7/3, 2023 at 10:16 Comment(0)
H
0

If you realy need to Console object you can compile your class from command line. Firstly in my java file first statement is package com.inputOutput;

Go in your project "src" folder and compile it like : "javac com/inputOutput/Password.java" 'com' and 'inputOutput' are folder(package). Run your class file in src folder
java com.inputOutput.Password". It had worked work for me.

Helsell answered 6/1, 2018 at 0:25 Comment(0)
T
0

You could use an Jframe.

JFrame frame = new JFrame("titile");

// prompt the user to enter their code
String code = JOptionPane.showInputDialog(frame, "promt here");
Technics answered 29/11, 2018 at 10:20 Comment(1)
How would one handle the input that's been given?Counterstamp
P
0

I abstracted it out, so when running in an IDE, it will use the scanner, but when running from the command line, it'll use the console:

import java.io.Console;
import java.util.Scanner;
    
public class UserInputReader {
  private final Console console;
  private final Scanner scanner;

  public UserInputReader() {
    console = System.console();
    scanner = console == null ? new Scanner(System.in) : null;
  }

  public String readLine() {
    return console != null ? console.readLine() : scanner.nextLine();
  }
    
  public String readPassword() {
    return console != null ? String.valueOf(console.readPassword()) : scanner.nextLine();
  }
}
Pul answered 21/4, 2023 at 6:57 Comment(0)
I
0

As a workaround I start a terminal from my project in intellij then I type:

$ java -cp target/classes org.enricogiurin.ocp17.ch14.UserInput

Where UserInput is the class whose main uses the java.io.Console.

I know it's not the expected solution, in fact I have written that it's a workaround.

Idonah answered 6/8, 2023 at 2:32 Comment(0)
D
-3

java.util.Scanner API is what you are looking for.

Determined answered 20/10, 2014 at 17:3 Comment(3)
Any explanations about why Scanner is what OP should use? What about other alternatives like BufferedReader? Also System.console() will also work if it is used properly.Fracas
Scanner API is a very simple API for reading the console inputs. It is very easy to get a hang of it, esp for the beginners. To start using the BufferedReader API, user should be aware of quite a few java.io related interfaces and the exact differences among them. It takes some time to get a hang of it and appreciate it. At least, that is what happened to me when there was no Scanner API, before java-1.5Determined
There's another answer here explaining scanner in detail with example: https://mcmap.net/q/146188/-trying-to-read-from-the-console-in-javaBeam

© 2022 - 2024 — McMap. All rights reserved.