4

Question:

How to take user input in jshell script? or what I'm doing wrong?

Note: I'm NOT looking how to pass arguments to jshell script.

Example:

For example script hello.java:

Scanner in = new Scanner(System.in);

System.out.print("Enter number n1: ");
int n1 = in.nextInt();
System.out.print("Enter number n2: ");
int n2 = in.nextInt();

System.out.println("n1 + n2 = "+ (n1 +n2));

/exit

It works if I type line by line in jshell, but then I run jshell hello.java it doesn't. Throws java.util.NoSuchElementException.

Output I getting:

@myMint ~/Java $ jshell hello.java 
Enter number n1: |  java.util.NoSuchElementException thrown: 
|        at Scanner.throwFor (Scanner.java:858)
|        at Scanner.next (Scanner.java:1497)
|        at Scanner.nextInt (Scanner.java:2161)
|        at Scanner.nextInt (Scanner.java:2115)
|        at (#3:1)
Enter number n2: |  java.util.NoSuchElementException thrown: 
|        at Scanner.throwFor (Scanner.java:858)
|        at Scanner.next (Scanner.java:1497)
|        at Scanner.nextInt (Scanner.java:2161)
|        at Scanner.nextInt (Scanner.java:2115)
|        at (#5:1)
n1 + n2 = 0

My system: Linux Mint 18.2(x64), JShell Version 9.0.1

my-
  • 490
  • 5
  • 16
  • 2
    Two ways to look at it. One if I consider the input in the script after `int n1 = in.nextInt();` as entered by you manually. Another what happens if you remove those Return(enter) from the scripts and run it as a single line with statements separated by semi-colon? But interestingly the comparison of script vs line by line is good to see the difference here and not to forget `throws NoSuchElementException - if input is exhausted` – Naman Jan 02 '18 at 16:15
  • @nullpointer I was thinking about first way. Adding `in.hasNextLine()` [check](https://stackoverflow.com/a/13729470/5322506) (tnx for pointing it) get rid of exception. But now feels like I need some kind of pause(hold until the user enters)..?? Second way... I'm a student(not native English speaker) and it gave my brain "little" what the hell I just read. I read your post few times, think what I just read, try single line script (results was same), read your post again, think again... and still feel lost. Did I miss smth? BTW thanks for your time. – my- Jan 02 '18 at 17:22

3 Answers3

4

Per default, jshell delegates execution to a remote VM. If you pass --execution local it uses the same VM process, which provides an instance of System.in as expected. Tailored to your question, the following call should do the trick:

jshell --execution local hello.java

See details via jshell --help-extra or browse the API documentation at https://docs.oracle.com/en/java/javase/11/docs/api/jdk.jshell/module-summary.html

Sormuras
  • 6,622
  • 29
  • 56
3

You can solve this issue, but not directly with JShell based code.

There is this project jshell_script_executor: https://github.com/kotari4u/jshell_script_executor

You can download it, and with small modification inside JShellScriptExecutor.java

from

try(JShell jshell = JShell.create()){

to

// This call will map System.in in your main code
// to System.in inside JShell evaluated code
try(JShell jshell =
  JShell.builder()
    .in(System.in)
    .out(System.out)
    .err(System.err)
    .build()){

and (also) small modification of your code (I know this is not exactly what you are looking for - we don't use Scanner here):

/* Put this code into file.jshell */
import java.io.*;

InputStreamReader read = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(read);
int n1;
System.out.print("Enter the number: ");
n1 = Integer.parseInt(in.readLine());

int n2;
System.out.print("Enter the number: ");
n2 = Integer.parseInt(in.readLine());

System.out.println("n1 + n2 = " + (n1 + n2));

you can get it running:

> javac src/main/java/com/sai/jshell/extension/JShellScriptExecutor.java
> java -cp src/main/java com.sai.jshell.extension.JShellScriptExecutor ./file.jshell
Enter the number: 1
Enter the number: 2
n1 + n2 = 3

Well ... in fact it will work with your code as well - slightly modified:

/* Put this code into file_scanner.java */
import java.util.Scanner;

Scanner in = new Scanner(System.in);

System.out.print("Enter number n1: ");
int n1 = in.nextInt();
System.out.print("Enter number n2: ");
int n2 = in.nextInt();

System.out.println("n1 + n2 = "+ (n1 +n2));

and give it a try

> java -cp src/main/java com.sai.jshell.extension.JShellScriptExecutor ./file_scanner.java
Enter number n1: 1
Enter number n2: 2
n1 + n2 = 3
Oo.oO
  • 9,723
  • 3
  • 19
  • 40
3

From JDK11 you can directly execute java source file:

$java Script.java

See Launch Single-File Source-Code Programs

Imaskar
  • 2,245
  • 21
  • 30