What I would like to do is wrap my Java program around the GHCI.
In my mind it should work like this:
Starting my Java program
Write down some Haskell function as Input for Java (i.e. reverse [1,2,3,4])
See the appropriate Haskell Output on my Java Console
Because I did not want to mess around with any language bridges I tried the clumsy way and used the Runtime.exec() approach.
This is my Code:
public static void main(String[] args) throws Exception {
Runtime r = Runtime.getRuntime();
Process p = r.exec("ghci");
OutputStream output = p.getOutputStream();
output.write("let x = 5\r\n".getBytes());
output.write("x".getBytes());
int tmp;
String result = "";
while ((tmp = p.getInputStream().read()) != -1) {
result += (char) tmp;
}
System.out.println(result);
p.destroy(); }
My problem here is that the read() method always returns a -1 and I cannot get the output. I dont even know if what I wrote created any Output.
Help would be appreciated. Thanks!
It is clear that Process p = r.exec("ghci"); did not successful for which read() method always returns a -1. Provide full path and check.
Process p = r.exec("/fullpath/ghci 2>&1");
p.waitFor();//You need to use this line of code
For confirmation first execute ls command first
Process p = r.exec("ls 2>&1");
Also modify your codes like below and try:-
public static void main(String[] args) throws Exception {
Runtime r = Runtime.getRuntime();
Process p = r.exec("ghci");
p.waitFor();
OutputStream output = p.getOutputStream();
ByteArrayOutputStream byte1=new ByteArrayOutputStream();
output.write(byte1.toByteArray());
String result=byte1.toString();
System.out.println(result);
p.destroy();
}
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’m developing an IDE kind of software for C/C++ using java (although there are lots of available, but I want my own) that can compile and execute C or C++ program. So I tried a simple program to compile and execute the C program in java using Process and ProcessBuilder.
Here is my simple java program which compiles and execute C program:
public class RunProgram {
public static void main(String[] args) throws Exception {
new ProcessBuilder("gcc", "-o", "first", "first.c").start().waitFor(); //To Compile the source file using gcc and wait for compilation
/*
Although I've to handle error-stream but
for now, my assumption is that there is no error
in program.
*/
ProcessBuilder run = new ProcessBuilder("./first");
execute.redirectErrorStream(true);
Process runProcess = run.start();
StreamReader sr = new StreamReader(runProcess.getInputStream());
new Thread(sr).start(); //A new thread to handle output of program .
//rest of coding to provide input using OutputStream of 'runProcess' and to close the stream.
}
}
class StreamReader implements Runnable {
private InputStream reader;
public StreamReader(InputStream inStream) {
reader = inStream;
}
#Override
public void run() {
byte[] buf = new byte[1024];
int size = 0;
try {
while ((size = reader.read(buf)) != -1) {
System.out.println(new String(buf));
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And here is my first.c program.
#include<stdio.h>
int main() {
int a;
int k;
printf("input a: ");
scanf("%d", &a);
for(k = 0; k < a; k++)
printf("k = %d\n", k);
return 0;
}
I want to create interactive IO console just like most of the IDEs or command terminals(Terminal in Linux bases OS and command prompt in Windows based OS). For above example: firstly, it should print “Input a: “and then wait for input to be provided and then rest of program. But It won’t work as I thought, as it doesn’t print the result of printf statement appeared before scanf until I provide input possibly using OutputStream.
I googled for my problem and visited many links but didn't get solution. Mean while, I found this link which suggest to append fflush after every printf statement or use setbuf or setvbuf methods (from some other sub-links) to clear the buffer. But a new person (who is going to learn C) might not be aware of fflush or these functions and he/she will never use it, as it doesn’t require in other IDEs or not even on terminals.
How can I solve this problem and can build integrated console for my IDE
Here is a glimpse of what I want:
From the comments above, think adding a little bit of explanation of how buffering for I/O streams works makes sense here.
What happens behind the scenes when calling printf(3) and the like is that the data is written to a buffer until the buffer fills up or some trigger happens.
The content of the buffer is then copied from the buffer to the actual output device/another output buffer ...
The trigger is usually encountering a line end (\n under Linux/Unix).
Thus a crude version of this buffering is:
struct buffered_file_t {
char* buffer;
size_t capacity;
size_t current_char;
FILE* file;
};
void flush_buffered(struct buffered_file_t* file) {
assert(0 != file);
assert(0 != file->buffer);
fwrite(file->buffer, file->current_char, 1, file->file);
file->current_char = 0;
}
void print(struct buffered_file_t* file, const char* str) {
assert(0 != file);
assert(0 != file->buffer);
assert(0 != str);
for(size_t i = 0; 0 != str[i]; ++i) {
if(file->current_char >= file->capacity - 1) flush_buffered(file);
file->buffer[file->current_char++] = str[i];
if('\n' == str[i]) flush_buffered(file);
}
}
Now, if you invoke print like
const size_t BUFSIZE = 100;
struct buffered_file_t stdout_buffered = {
.buffer = calloc(1, BUFSIZE),
.capacity = BUFSIZE,
.current_char = 0,
.file= stdout,
};
print(&stdout_buffered, "Naglfar\n");
print(&stdout_buffered, "Surthur");
You won't see Surthur appear onstdout ever.
In order to have it written from the buffer to stdout, you have to either
call flush_buffered explicitly
Disable buffering by reducing the buffer size (buffered_file.capacity = 1 in the example above)
In your case, you cannot invoke fflush(3) explicitly (that's what you stated as requirement). thus the only means left is disabling buffering.
How to do this is OS dependent, IMHO.
For Linux, look at stdbuf(1) from the Coreutils package to find out how to diable buffering for certain streams of foreign processes.
Under GNU/Linux, for switching off buffering for the standard I/O streams, you could use stdbuf(1)like so:
....
ProcessBuilder run = new ProcessBuilder("stdbuf", "-o0", "./first");
....
Add -e0 and -i0 options if you want to turn off buffering for stderr and stdin as well.
Of course, it would be nicer if you would not have to rely upon external tools but could do switching off buffering in your own code - simplest thing is to have a look at the source of stdbuf, but I guess it would end up in you having to use the JNI, and then, I guess, I would just stick to stdbuf ...
I'm using a Raspberry Pi to receive the UID of some RFID cards from a RC522 reader. The python script I'm running is here: https://github.com/mxgxw/MFRC522-python
For various reasons I won't go into, I have to process these IDs in Java.
It seems the most viable solution is to run the python script and read in the result into Java. The problem is, the Python code gives continuous output, i.e. it will print the ID of the card into the console window as and when a card is tapped onto the reader, and will only terminate on a user's command.
I'm currently using a ProcessBuilder to execute the script, however it seems like it's more suited to run the program and read in the immediate result back to Java (which of course is null if I haven't tapped a card onto the reader). I've tried executing the code in a while(true) loop to continuously start the process - but this doesn't work:
import java.io.*;
public class PythonCaller {
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
// set up the command and parameter
String pythonScriptPath = "/home/pi/MFRC522-python/Read.py";
String[] cmd = new String[3];
cmd[0] = "sudo";
cmd[1] = "python"; // check version of installed python: python -V
cmd[2] = pythonScriptPath;
// create runtime to execute external command
ProcessBuilder pb = new ProcessBuilder(cmd);
// retrieve output from python script
pb.redirectError();
while(true){
Process p = pb.start();
System.out.println("Process Started...");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
int ret = new Integer(in.readLine()).intValue();
System.out.println("value is : "+ret);
}
}
}
The output on the console window is blank - no exceptions thrown or println's.
Any help would be massively appreciated!!
Thanks
EDIT - I've surrounded my code in a try/catch to see if there's anything at all being thrown, and it doesn't seem to be the case
I use the following programs to try to reproduce the problem
PythonCaller.java
import java.io.*;
public class PythonCaller {
public static void main(String[] args) throws IOException {
// set up the command and parameter
String pythonScriptPath = "/home/pi/test.py";
String[] cmd = { "python", pythonScriptPath };
// create runtime to execute external command
ProcessBuilder pb = new ProcessBuilder(cmd);
// retrieve output from python script
pb.redirectError();
while(true){
Process p = pb.start();
System.out.println("Process Started...");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
int ret = new Integer(in.readLine()).intValue();
System.out.println("value is : "+ret);
}
}
}
test.py
uid =(123,456,789,999)
print "Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3])
The method pb.redirectError() doesn't modify anything. It returns a value, your codes does nothing with it. (see http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#redirectError%28%29). What you want is probably redirectErrorStream(boolean redirectErrorStream)
The second line of the python test program is taken directly from "Read.py" (line 44). It causes an error with the java intValue() method. If I replace it with String ret = in.readLine();, the program seems to work.
Since the Process p = pb.start(); is inside the loop, the python subprogram is called repeatedly.
The next step should be to try running the python program manually in a console, see what it does.
(n.b. I had to remove "sudo" and change paths to be able to test on my system, you should have no problems replacing things for your setup).
I've managed to get around it by editing my Python script - it returns null if there's no card on the reader, and the UID if there is.
I'll probably use observer pattern or similar on the Java end to detect when there's a card. Very resource intensive but it'll have to do for now!
How can I run an another java process (with a console) in Linux?
I know I should use ProcessBuilder or Runtime.getRuntime().exec() to execute a command,
but I want to know how I can show an separate X-window command terminal (ex. /usr/bin/xterm) or at least show an console-terminal looking window and run a java process with stdin,stdout,stderr on that.
Is there any solution? I heard the Process.getOutputStream() doesn't work on xterm, but haven't tried it yet (Because I'm using Windows..)
EDIT: The java program I want to execute uses jline, which uses JNI...
To start terminl you can simply run following code:
new ProcessBuilder("/usr/bin/xterm").start();
But I guess, that is not you really need. Because, even you pass command to run, let's say ls as argument:
new ProcessBuilder("/usr/bin/xterm", "-e", "ls").start();
You will get output from xterm(not from ls). If you want to start process and get output, you need to do it like that:
public static void main(String[] args) throws Exception {
// get content of the "/usr/bin" directory
ProcessBuilder pb = new ProcessBuilder("ls", "/usr/bin");
pb.redirectErrorStream(true);
Process p = pb.start();
InputStream is = p.getInputStream();
System.out.println(toString(is));
is.close();
}
public static String toString(InputStream is) throws IOException {
Writer writer = new StringWriter();
char[] buffer = new char[1024];
Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
int n;
while ((n = reader.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
return writer.toString();
}
I'm aware how to open an exe program with parameters in Java from finding the answer online. However my specific shortcut is a bit complicated for me to understand.
I'm trying to open a shortcut which has the following target:
C:\Windows\System32\javaw.exe -cp jts.jar;total.2012.jar -Dsun.java2d.noddraw=true -Dswing.boldMetal=false -Dsun.locale.formatasdefault=true -Xmx768M -XX:MaxPermSize=128M jclient/LoginFrame C:\Jts
In my program I've split up the location and what I think are the parameters. However when I run the program I get the error 'Could not create Java Virtual Machine, Program will Exit'. Can someone with a better understanding of whats going on explain what I might be doing wrong or point me in a direction where I can read up?
String location = "C:\\Windows\\System32\\javaw.exe";
String p1="-cp jts.jar;total.2012.jar";
String p2="-Dsun.java2d.noddraw=true";
String p3="-Dswing.boldMetal=false";
String p4="-Dsun.locale.formatasdefault=true";
String p5="-Xmx768M";
String p6="-XX:MaxPermSize=128M";
String p7="jclient/LoginFrame" ;
String p8 = "C:\\Jts";
try {
Process p = new ProcessBuilder(location,p1,p2,p3,p4,p5,p6,p7,p8).start();
} catch (IOException ex) {
Logger.getLogger(Openprogramtest.class.getName()).log(Level.SEVERE, null, ex);
}
Each String you pass to ProcessBuilder is a separate argument (except the first one, which is the command).
Think of it like the args[] which are passed to your main method. Each String would be a separate element in the array.
I suspect that p1 is been interpreted as a single argument, when it should actually be two...
Try separating this argument into two separate parameters
String location = "C:\\Windows\\System32\\javaw.exe";
String p1="-cp";
String p2="jts.jar;total.2012.jar";
String p3="-Dsun.java2d.noddraw=true";
String p4="-Dswing.boldMetal=false";
String p5="-Dsun.locale.formatasdefault=true";
String p6="-Xmx768M";
String p7="-XX:MaxPermSize=128M";
String p8="jclient/LoginFrame" ;
String p9 = "C:\\Jts";
Amendment
Look at the -cp parameter, it appears that the class path elements are relative to the location that the command is executed. This suggests that you need to use the ProcessBuilder#directory(File) to specify the location that the command should executed from.
For example, if you program is installed in C:\Program Files\MyAwesomeApp, but you run it from the context of C:\Desktop, then Java won't be able to find the Jar files it needs, generally raising a ClassNotFound exception.
Instead, you need to tell ProcessBuilder that you want the command to executed from within the C:\Program Files\MyAwesomeApp context.
For example...
ProcessBuilder pb = new ProcessBuilder(...);
pb.directory(new File("C:\Program Files\MyAwesomeApp"));
// Other settings...
Process p = pb.start();
Updated from running example
Just to make the point. I built myself a little Java program that simple printed a simple message to the standard out.
When I run this, it works as expected...
try {
String params[] = new String[]{
"C:\\Windows\\System32\\javaw.exe",
"-cp",
"C:\\...\\TestSimpleProcessBuilder\\build\\classes",
"-Dsun.java2d.noddraw=true",
"-Dswing.boldMetal=false",
"-Dsun.locale.formatasdefault=true",
"-Xmx768M",
"-XX:MaxPermSize=128M",
"testsimpleprocessbuilder/HelloWorld",
"Boo"
};
ProcessBuilder pb = new ProcessBuilder(params);
pb.redirectErrorStream();
Process p = pb.start();
InputStream is = p.getInputStream();
int in = -1;
while ((in = is.read()) != -1) {
System.out.print((char) in);
}
is = p.getErrorStream();
in = -1;
while ((in = is.read()) != -1) {
System.out.print((char) in);
}
System.out.println("p exited with " + p.exitValue());
} catch (IOException ex) {
Logger.getLogger(TestSimpleProcessBuilder.class.getName()).log(Level.SEVERE, null, ex);
}
When I change the arguments from
"-cp",
"C:\\...\\TestSimpleProcessBuilder\\build\\classes",
to
"-cp C:\\...\\TestSimpleProcessBuilder\\build\\classes",
It fails with...
And outputs
Unrecognized option: -cp
C:\DevWork\personal\java\projects\wip\StackOverflow\TestSimpleProcessBuilder\build\classes
And if you're wondering, this is the little test program I wrote that gets run...
package testsimpleprocessbuilder;
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello world - world says " + (args.length > 0 ? args[0] : "Nothing"));
}
}