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
Related
I found this as one of the ways to run (using exec() method) python script from java. I have one simple print statement in python file. However, my program is doing nothing when I run it. It neither prints the statement written in python file nor throws an exception. The program just terminates doing nothing:
Process p = Runtime.getRuntime().exec("C:\\Python\\Python36-32\\python.exe C:\\test2.py");
Even this is not creating the output file:
Process p = Runtime.getRuntime().exec("C:\\Python\\Python36-32\\python.exe C:\\test2.py output.txt 2>&1");
What is the issue?
I think you could try your luck with the ProcessBuilder class.
If I read the Oracle documentation correctly, the std inputs and outputs are directed to pipes by default but the ProcessBuilder has an easy method for you to explicitly set output (or input) to a file on your system or something else.
If you want your Python program to use the same output as your Java program (likely stdout and stderr), you can use stg like this:
ProcessBuilder pb = new ProcessBuilder("C:\\Python\\Python36-32\\python.exe", "C:\\test2.py");
pb.redirectOutput(Redirect.INHERIT);
Process p = pb.start();
You can use the ProcessBuilder API, redirecting the output to a file and then wait for the result.
public class Main {
public static final String PYTHON_PATH = "D:\\Anaconda3\\python.exe";
public static final String PATH_TO_SCRIPT = "D:\\projects\\StartScript\\test.py";
public static void main(String[] args) throws IOException, InterruptedException {
ProcessBuilder builder = new ProcessBuilder();
builder.command(PYTHON_PATH, PATH_TO_SCRIPT);
// Redirect output to a file
builder.redirectOutput(new File("output.txt"));
builder.start().waitFor();
// Print output to console
ProcessBuilder.Redirect output = builder.redirectOutput();
File outputFile = output.file();
BufferedReader br = new BufferedReader(new FileReader(outputFile));
String st;
while ((st = br.readLine()) != null) {
System.out.println(st);
}
}
}
The python file test.py contains a simple print statement:
print("Hello from python")
I guess it would be even simpler, if you do not need to wait for the result.
Using the Process API should work, too.
Like in your example (I am using the same constants declared above):
Process p = Runtime.getRuntime().exec(PYTHON_PATH + " " + PATH_TO_SCRIPT);
p.waitFor();
byte[] buffer = new byte[1024];
byte[] errBuffer = new byte[1024];
p.getInputStream().read(buffer);
p.getErrorStream().read(errBuffer);
System.out.println(new String(buffer));
System.out.println(new String(errBuffer));
To see the output of the print statement, you need to wait and redirect the streams. Same for the error stream.
Now if you break the python script like this:
print("Hello from python')
you should be able to see the error printed as well.
One way to start a python process is using an entrypoint - test.cmd
echo Hello
python hello.py
here is hello.py
#!/usr/bin/env python3
import os
if not os.path.exists('dir'):
os.makedirs('dir')
Here is my Java code:
public static void main(String[] args) throws IOException {
try {
Process p = Runtime.getRuntime().exec("test.cmd");
p.waitFor();
Scanner sc = new Scanner(p.getInputStream());
while(sc.hasNextLine()){
System.out.println(sc.nextLine());
}
sc.close();
} catch (Exception err) {
err.printStackTrace();
}
}
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.
I need a way to run another java application from within my application. I want to recive its outputs into a JTextArea and send it inputs via a JTextBox.
Depends.
You could use a custom URLClassLoader to load the second applications jar and call the main classes main method directly. Obviously, the issue there is getting the output from the program ;)
The other solution would be to use a ProcessBuilder to launch a java process and read the output via the InputStream
The problem here is trying to find the java executable. In general, if it's in the path you should be fine.
You can have a look at this as a base line example of how to read the inputstream
UPDATED with Example
This is my "output" program that produces the output...
public class Output {
public static void main(String[] args) {
System.out.println("This is a simple test");
System.out.println("If you can read this");
System.out.println("Then you are to close");
}
}
This is my "reader" program that reads the input...
public class Input {
public static void main(String[] args) {
// SPECIAL NOTE
// The last parameter is the Java program you want to execute
// Because my program is wrapped up in a jar, I'm executing the Jar
// the command line is different for executing plain class files
ProcessBuilder pb = new ProcessBuilder("java", "-jar", "../Output/dist/Output.jar");
pb.redirectErrorStream();
InputStream is = null;
try {
Process process = pb.start();
is = process.getInputStream();
int value;
while ((value = is.read()) != -1) {
char inChar = (char)value;
System.out.print(inChar);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
You can also checkout Basic I/O for more information
import java.io.*;
public class ConsoleDemo {
public static void main(String[] args) {
String str;
Console con;
con = System.console();
if (con == null)
return;
str = con.readLine("Enter a string : ");
con.printf("Here is your string %s", str);
}
}
I copied this code from the book, which says that I would get a prompt on the screen for entering a string, but my IDE just gives the message that the execution has termination, without giving me a prompt.
Eclipse nor Netbeans supports the use of Console. The Console.istty() method will return false and you will not have a console to use.
You can change your code to the following and achieve the same result and be able to run it from within the IDE.
import java.io.*;
public class ConsoleDemo {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter a String and press enter");
System.out.println("You entered the String: " + scan.nextLine()
}
}
What IDE are you using? This code works just fine when you run it from the command line, so the problem clearly lies with the configuration of your IDE.
Use the following commands to compile and run your code from the command line:
javac ConsoleDemo.java
java ConsoleDemo
Edit: as this link suggests, using System.Console doesn't always work in IDEs. Alternatively you can just use System.in.
Your code is working from both Eclipse and Command Prompt.
Try this way as well if you are using Java 5 or +
Scanner in = new Scanner(System.in);
System.out.print("Enter a String : ");
String string = in.nextLine();
System.out.println("Here is your String : " + string);
By default, eclipse does not associate console with the JVM. You may have to configure it. But if you run it in command line, it will have console definitely and hence it will run without any problem.
It is because your IDE runs this code by javaw.exe (windowless -> no console) not java.exe (with console window) command, so System.console() returns null.
Standard solution is to read data from input stream which is represented by System.in so you can use for instance Scanner like
Scanner keybord = new Scanner(System.in);
String line = keybord.readLine();
I need to execute the less command, with paging, from my Java console application. However, the only method I found to execute external commands is Runtime.getRuntime().exec(), which requires me to write/read input/output via streams. So commands like cat work (and less does in fact act like cat), but I need the paging functionality.
In C, I'd use system(). In Ruby, Kernel.exec does the job.
Is there any way to get this done in Java?
When you execute an external process with Runtime.exec() its standard input and output streams are not connected to the terminal from which you are running the Java program. You can use shell redirection to connect it, but first you need to know what terminal to use. There is no way to find the terminal using the standard API but probably you can find an open source library that does it.
To see that it can be done, this program opens itself in less:
public class Test {
public static void main(String[] args) throws Exception {
Process p = Runtime.getRuntime().exec(
new String[] {"sh", "-c",
"less Test.java < "+args[0] + " > "+args[0]});
System.out.println("=> "+p.waitFor());
}
}
To run it you should use java Test $(tty). The tty program prints the name of the terminal connected to its stdin.
I'm not too sure about the portability of this solution; at least it works on Linux.
List item
The following program will work, initially it prints 10 lines , then press enter it will print next line till end of the file.
run program like
java Less $fileName
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class Less
{
public static void main(String args[]) throws IOException
{
FileReader reader = new FileReader(args[0]);
BufferedReader buff = new BufferedReader(reader);
String readLine;
int lineCount = 0;
while ((readLine = buff.readLine()) != null)
{
System.out.println(readLine);
lineCount++;
if (lineCount > 10)
{
Scanner scanner = new Scanner(System.in);
scanner.nextLine();
}
}
}
}