I have this simple code:
public class Example {
public Example() {
Scanner scanner = new Scanner(System.in);
int row = scanner.nextInt(); // exception at this line
scanner.close();
}
public static void main(String[] args) {
Example ex1 = new Example(); // this line successfully operate
Example ex2 = new Example(); // exception : no such element exception at above line
}
}
I don't know why I always receive this Exception, when code run to ex2.
The problem is because you close the Scanner which in turn closes the underlying InputStream (in this case stdin). When you try to use stdin in again the Scanner is unable to retrieve any data because stdin has been closed.
If running directly from the commandlne then the correct way to provide access to stdin is to use the Console class. The console class provides a Reader wrapped around stdin that has a no-op close method. eg.
public class Example {
public Example() {
Scanner scanner = new Scanner(System.console().reader());
// note change on above line
int row = scanner.nextInt();
scanner.close();
}
}
Note, if you access stdin other than via the Console class then you'll likely cause problems for yourself. And if you invoke your java program other than directly from the command line then you will not get access to the console. For instance, the following will invokations cause problems.
echo 2 3 | java Example
or
Process p = new ProcessBuilder("java", "Example").start();
// write data to process
You Should add if(Scanner.hasNext()) before invoking scanner.nextInt();
You have the exception because no int found to be read.
Related
I am trying to develop an online Java IDE. I am not able to get input from another java program.
The second program: HelloWorld.java
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello world..................");
Scanner sc = new Scanner(System.in);
System.out.println("Enter Name");
String name = sc.nextLine();
System.out.println("you entered " + name);
sc.close();
}
}
public class Demo {
public static void main(String[] args) {
Process pro = Runtime.getRuntime().exec(javac HelloWorld.java);
Process pro1 = Runtime.getRuntime().exec(java HelloWorld);
}
}
The problem is that when I compile and run the above program I am getting "Enter Name" of System.out.println("Enter Name"); in HelloWorld.java. However, after that nothing happens.
It is not the same "Runtime". Calling exec starts a new process.
Interaction with a running process should use the input and output stream from executing the process.
e.g use the following:
Process p = Runtime.getRuntime().exec(*******);
InputStream is = p.getInputStream();
InputStream es = p.getErrorStream();
OutputStream os = p.getOutputStream();
start with a simple example of passing param to the process manually and afterwards see how you can connect streams from different processes
I need to dialogue with an external c++ console program (read output and write input). I read from the application with a Thread (and it works), but when it needs input, it works only the first time, then the stream probably remains empty, and it doesn't receive the second input (and external program closes).
The application i'm using is a simple .exe wrote in c++ that:
print "Insert first input"
scan input1
print input1
print "Insert second input"
scan input2
print input2
Main class:
import java.io.*;
import java.util.Scanner;
public class ExampleCom {
public static Communication com = new Communication();
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
String s;
com.read();
while(true)
{
s = in.nextLine();
com.write(s);
}
}
Communication class:
public class Communication
{
Process p;
OutputStream writer;
public InputStream reader = null;
Read r; //Class that with a loop read all exe input
Communication()
{
try{
p = Runtime.getRuntime ().exec ("C:\\esempio.exe");
writer = p.getOutputStream();
reader = p.getInputStream();
}catch(Exception e){}
}
public void read()
{
r = new Read();
Thread threadRead = new Thread(r);
threadRead.start();
}
public void write(String s)
{
try{
writer.write(s.getBytes());
writer.flush();
writer.close();
}catch(Exception e){}
}
}
How can I send my string (like "writer.write('hello')") when the external application needs it?
The problem is that in your write() method, you have the line
writer.close();
which means that after calling it the first time, you are closing the input stream to your C++. As far as it is concerned, it sees the "end of file" marker after your first input.
What you should do is put the close() in a separate method, and call that method only when you are done working with that process.
Now, as your target program expects text input and will only interpret the input if it gets an end-of-line (as per your answer to the question in my comment), you should supply that end-of-line to it.
Instead of doing raw byte-writes, I think a better approach would be to use a PrintWriter for that output stream, and use as naturally as you use System.out.println(). It can also save you on the flush() part.
You are interpreting it incorrectly when you see that your program is not reading the input until you close(). It's not waiting - it sends it as soon as you call flush(). But the C++ waits for either an end-of-file or an end-of-line, and since you are not giving it an end-of-line, then only close(), that sends it end-of-file, causes it to accept the input. But then you can no longer send any further data.
So the solution is, first, to define your writer as a PrintWriter. Instead of
OutputStream writer;
Use
PrintWriter writer;
And instead of
writer = p.getOutputStream();
Use
writer = new PrintWriter(p.getOutputStream(), true);
The true there will give you auto-flush whenever you use the println() command.
Now, your write method should be:
public void write(String s)
{
writer.println(s);
}
Note that a PrintWriter doesn't produce exceptions, so if you care about errors, you have to check for them using checkError().
And of course, have the close() in a separate method, as I mentioned before.
Because the write() method might throw an IOException, it is advisable to call the close() method inside a finally block.Place the writer.close() method outside the try clause:
finally {
if(writer != null) {
writer.close();
}
I'm writing a program that executes another Java program by using the Class and Method classes to invoke the main method. This other program then tries to read from System.in. In order to pass arguments to the program, I set System.in to a PipedInputStream that is connected to a PipedOutputStream. I pass the arguments the other program requests to the PipedOutputStream, then invoke the main method.
However, as soon as the method is invoked, the program deadlocks. Why is that? Theoretically, the other program should have access to the arguments, since they're already available in the PipedInputStream.
I can't change the way the other program reads the input, so this solution wouldn't work.
Here some example code:
The part where I assign the PipedStreams
PipedInputStream inputStream = new PipedInputStream();
PipedStringOutputStream stringStream = new PipedStringOutputStream(); // custom class
try {
stringStream.connect(inputStream);
} catch (IOException e2) {
e2.printStackTrace();
}
System.setIn(inputStream);
The part where I invoke the method:
Class main = classes.get(className);
try {
Method m = main.getMethod("main", String[].class);
// write all parameters to System.in
String[] params = getParams(); // custom method, works (params is not empty)
for(int j = 0; j < params.length; j++) {
stringStream.write(params[j]);
}
params = null;
m.invoke(null, (Object) params); // this is were the program stops
} catch(Exception e) {}
The PipedStringOutputStream class:
public class PipedStringOutputStream extends PipedOutputStream {
public void write(String output) throws IOException {
this.write((output + "\n").getBytes());
flush();
}
}
My test program that reads from System.in:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
System.out.println(sc.nextLine());
}
}
So what is the problem? Do I have to start the Streams in Threads? Why doesn't the other program read the input from the PipedInputStream?
The javadoc of PipedInputStream explicitely says:
Typically, data is read from a PipedInputStream object by one thread and data is written to the corresponding PipedOutputStream by some other thread. Attempting to use both objects from a single thread is not recommended, as it may deadlock the thread.
(emphasis mine)
Write your input to a byte array using a ByteArrayOutputStream. Then construct a ByteArrayInputStream from this byte array, and set System.in to this ByteArrayInputStream.
I use java.util.Scanner to read the commands from the console.
try
{
ICommand cmd = cmdReader.ReadCommand();
cmd.Execute(conn);
}
catch(MyException ex)
{
// print a message about unknown command
continue;
}
Where ReadCommand is implemented as follows:
try (Scanner scanIn = new Scanner(System.in))
{
if (!scanIn.hasNextLine()) return null;
line_ = scanIn.nextLine();
ICommand command = parser_.ParseCommand(line_);
return command;
}
In the first iteration code works fine, I write something invalid (not a command), the code prints a warning and continues. But other iterations return null here if (!scanIn.hasNextLine()) return null; even if I write something in a console. Looks like java.util.Scanner doesn't see the input. Am I doing something wrong? And how then I can wait for the user input (don't want to use the cycle with sleep)?
You should not create a new Scanner instance each time you call ReadCommand. Create one and reuse it while reading input.
From the documentation:
When a Scanner is closed, it will close its input source if the source implements the Closeable interface.
So, your System.in stream is closed after you read the first input.
See also Java Scanner does not wait for input
I know how to use string args to get the input from the command-line, and it is working fine with input = args[0] where my input is java.exe program s1.in
But I need to run a compare program in terminal. So my input must have the "<" symbol. However, then I can't get my input values using input = args[1]. When I type this in, the args.length become 0. Why does this happen?
As an aside, does anyone know how to best search for this kind of term in google? Itthink google does not recognize "<" in the search entry.
Thank you
It's because when you use xyzzy <inputfile, your shell runs xyzzy and "connects" that file to your standard input. It then expects you to read that standard input to get your data - you never see the argument because it's removed from the command line (or, more likely, never added to your argument list).
That's why many programs will process a file if given, otherwise they'll read their data from standard input. And that's exactly what you need to do here.
For doing this, you'll probably want something like:
import java.io.*;
class Test {
public static void main(String args[]) {
InputStreamReader inp = null;
Boolean isStdIn = false;
try {
if (args.length > 0) {
inp = new InputStreamReader(new FileInputStream(args[0]));
} else {
inp = new InputStreamReader(System.in);
isStdIn = true;
}
// Now process inp.
if (isStdIn)
inp.close();
} catch (Exception e) {
System.exit(1);
}
}
}
It selects either the file (if available) or the standard input stream for reading.
Often, the most easy way is to use Scanner:
Scanner scaner = new Scanner (System.in);